• 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 
setEnableStateNative(JNIEnv * env,jobject object,jbyteArray address,jboolean enabled)438 static jboolean setEnableStateNative(JNIEnv* env, jobject object,
439                                      jbyteArray address, jboolean enabled) {
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->SetEnableState(*tmpraw, enabled);
455   env->ReleaseByteArrayElements(address, addr, 0);
456   return JNI_TRUE;
457 }
458 
groupAddNodeNative(JNIEnv * env,jobject object,jint group_id,jbyteArray address)459 static jboolean groupAddNodeNative(JNIEnv* env, jobject object, jint group_id,
460                                    jbyteArray address) {
461   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
462   jbyte* addr = env->GetByteArrayElements(address, nullptr);
463 
464   if (!sLeAudioClientInterface) {
465     LOG(ERROR) << __func__ << ": Failed to get the Bluetooth LeAudio Interface";
466     return JNI_FALSE;
467   }
468 
469   if (!addr) {
470     jniThrowIOException(env, EINVAL);
471     return JNI_FALSE;
472   }
473 
474   RawAddress* tmpraw = (RawAddress*)addr;
475   sLeAudioClientInterface->GroupAddNode(group_id, *tmpraw);
476   env->ReleaseByteArrayElements(address, addr, 0);
477 
478   return JNI_TRUE;
479 }
480 
groupRemoveNodeNative(JNIEnv * env,jobject object,jint group_id,jbyteArray address)481 static jboolean groupRemoveNodeNative(JNIEnv* env, jobject object,
482                                       jint group_id, jbyteArray address) {
483   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
484   if (!sLeAudioClientInterface) {
485     LOG(ERROR) << __func__ << ": Failed to get the Bluetooth LeAudio Interface";
486     return JNI_FALSE;
487   }
488 
489   jbyte* addr = env->GetByteArrayElements(address, nullptr);
490   if (!addr) {
491     jniThrowIOException(env, EINVAL);
492     return JNI_FALSE;
493   }
494 
495   RawAddress* tmpraw = (RawAddress*)addr;
496   sLeAudioClientInterface->GroupRemoveNode(group_id, *tmpraw);
497   env->ReleaseByteArrayElements(address, addr, 0);
498   return JNI_TRUE;
499 }
500 
groupSetActiveNative(JNIEnv * env,jobject object,jint group_id)501 static void groupSetActiveNative(JNIEnv* env, jobject object, jint group_id) {
502   LOG(INFO) << __func__;
503   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
504 
505   if (!sLeAudioClientInterface) {
506     LOG(ERROR) << __func__ << ": Failed to get the Bluetooth LeAudio Interface";
507     return;
508   }
509 
510   sLeAudioClientInterface->GroupSetActive(group_id);
511 }
512 
setCodecConfigPreferenceNative(JNIEnv * env,jobject object,jint group_id,jobject inputCodecConfig,jobject outputCodecConfig)513 static void setCodecConfigPreferenceNative(JNIEnv* env, jobject object,
514                                            jint group_id,
515                                            jobject inputCodecConfig,
516                                            jobject outputCodecConfig) {
517   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
518 
519   if (!env->IsInstanceOf(inputCodecConfig,
520                          android_bluetooth_BluetoothLeAudioCodecConfig.clazz) ||
521       !env->IsInstanceOf(outputCodecConfig,
522                          android_bluetooth_BluetoothLeAudioCodecConfig.clazz)) {
523     ALOGE("%s: Invalid BluetoothLeAudioCodecConfig instance", __func__);
524     return;
525   }
526 
527   jint inputCodecType = env->CallIntMethod(
528       inputCodecConfig,
529       android_bluetooth_BluetoothLeAudioCodecConfig.getCodecType);
530 
531   btle_audio_codec_config_t input_codec_config = {
532       .codec_type = static_cast<btle_audio_codec_index_t>(inputCodecType)};
533 
534   jint outputCodecType = env->CallIntMethod(
535       outputCodecConfig,
536       android_bluetooth_BluetoothLeAudioCodecConfig.getCodecType);
537 
538   btle_audio_codec_config_t output_codec_config = {
539       .codec_type = static_cast<btle_audio_codec_index_t>(outputCodecType)};
540 
541   sLeAudioClientInterface->SetCodecConfigPreference(
542       group_id, input_codec_config, output_codec_config);
543 }
544 
setCcidInformationNative(JNIEnv * env,jobject object,jint ccid,jint contextType)545 static void setCcidInformationNative(JNIEnv* env, jobject object, jint ccid,
546                                      jint contextType) {
547   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
548   if (!sLeAudioClientInterface) {
549     LOG(ERROR) << __func__ << ": Failed to get the Bluetooth LeAudio Interface";
550     return;
551   }
552 
553   sLeAudioClientInterface->SetCcidInformation(ccid, contextType);
554 }
555 
setInCallNative(JNIEnv * env,jobject object,jboolean inCall)556 static void setInCallNative(JNIEnv* env, jobject object, jboolean inCall) {
557   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
558   if (!sLeAudioClientInterface) {
559     LOG(ERROR) << __func__ << ": Failed to get the Bluetooth LeAudio Interface";
560     return;
561   }
562 
563   sLeAudioClientInterface->SetInCall(inCall);
564 }
565 
sendAudioProfilePreferencesNative(JNIEnv * env,jint groupId,jboolean isOutputPreferenceLeAudio,jboolean isDuplexPreferenceLeAudio)566 static void sendAudioProfilePreferencesNative(
567     JNIEnv* env, jint groupId, jboolean isOutputPreferenceLeAudio,
568     jboolean isDuplexPreferenceLeAudio) {
569   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
570   if (!sLeAudioClientInterface) {
571     LOG(ERROR) << __func__ << ": Failed to get the Bluetooth LeAudio Interface";
572     return;
573   }
574 
575   sLeAudioClientInterface->SendAudioProfilePreferences(
576       groupId, isOutputPreferenceLeAudio, isDuplexPreferenceLeAudio);
577 }
578 
579 static JNINativeMethod sMethods[] = {
580     {"classInitNative", "()V", (void*)classInitNative},
581     {"initNative", "([Landroid/bluetooth/BluetoothLeAudioCodecConfig;)V",
582      (void*)initNative},
583     {"cleanupNative", "()V", (void*)cleanupNative},
584     {"connectLeAudioNative", "([B)Z", (void*)connectLeAudioNative},
585     {"disconnectLeAudioNative", "([B)Z", (void*)disconnectLeAudioNative},
586     {"setEnableStateNative", "([BZ)Z", (void*)setEnableStateNative},
587     {"groupAddNodeNative", "(I[B)Z", (void*)groupAddNodeNative},
588     {"groupRemoveNodeNative", "(I[B)Z", (void*)groupRemoveNodeNative},
589     {"groupSetActiveNative", "(I)V", (void*)groupSetActiveNative},
590     {"setCodecConfigPreferenceNative",
591      "(ILandroid/bluetooth/BluetoothLeAudioCodecConfig;Landroid/bluetooth/"
592      "BluetoothLeAudioCodecConfig;)V",
593      (void*)setCodecConfigPreferenceNative},
594     {"setCcidInformationNative", "(II)V", (void*)setCcidInformationNative},
595     {"setInCallNative", "(Z)V", (void*)setInCallNative},
596     {"sendAudioProfilePreferencesNative", "(IZZ)V",
597      (void*)sendAudioProfilePreferencesNative},
598 };
599 
600 /* Le Audio Broadcaster */
601 static jmethodID method_onBroadcastCreated;
602 static jmethodID method_onBroadcastDestroyed;
603 static jmethodID method_onBroadcastStateChanged;
604 static jmethodID method_onBroadcastMetadataChanged;
605 
606 static LeAudioBroadcasterInterface* sLeAudioBroadcasterInterface = nullptr;
607 static std::shared_timed_mutex sBroadcasterInterfaceMutex;
608 
609 static jobject sBroadcasterCallbacksObj = nullptr;
610 static std::shared_timed_mutex sBroadcasterCallbacksMutex;
611 
612 #define VEC_UINT8_TO_UINT32(vec)                                          \
613   ((vec.data()[3] << 24) + (vec.data()[2] << 16) + (vec.data()[1] << 8) + \
614    vec.data()[0])
615 
616 #define VEC_UINT8_TO_UINT16(vec) (((vec).data()[1] << 8) + ((vec).data()[0]))
617 
RawPacketSize(const std::map<uint8_t,std::vector<uint8_t>> & values)618 size_t RawPacketSize(const std::map<uint8_t, std::vector<uint8_t>>& values) {
619   size_t bytes = 0;
620   for (auto const& value : values) {
621     bytes += (/* ltv_len + ltv_type */ 2 + value.second.size());
622   }
623   return bytes;
624 }
625 
prepareRawLtvArray(JNIEnv * env,const std::map<uint8_t,std::vector<uint8_t>> & metadata)626 jbyteArray prepareRawLtvArray(
627     JNIEnv* env, const std::map<uint8_t, std::vector<uint8_t>>& metadata) {
628   auto raw_meta_size = RawPacketSize(metadata);
629 
630   jbyteArray raw_metadata = env->NewByteArray(raw_meta_size);
631   if (!raw_metadata) {
632     LOG(ERROR) << "Failed to create new jbyteArray for raw LTV";
633     return nullptr;
634   }
635 
636   jsize offset = 0;
637   for (auto const& kv_pair : metadata) {
638     // Length
639     const jbyte ltv_sz = kv_pair.second.size() + 1;
640     env->SetByteArrayRegion(raw_metadata, offset, 1, &ltv_sz);
641     offset += 1;
642     // Type
643     env->SetByteArrayRegion(raw_metadata, offset, 1,
644                             (const jbyte*)&kv_pair.first);
645     offset += 1;
646     // Value
647     env->SetByteArrayRegion(raw_metadata, offset, kv_pair.second.size(),
648                             (const jbyte*)kv_pair.second.data());
649     offset += kv_pair.second.size();
650   }
651 
652   return raw_metadata;
653 }
654 
getAudioLocationOrDefault(const std::map<uint8_t,std::vector<uint8_t>> & metadata,jlong default_location)655 static jlong getAudioLocationOrDefault(
656     const std::map<uint8_t, std::vector<uint8_t>>& metadata,
657     jlong default_location) {
658   if (metadata.count(
659           bluetooth::le_audio::kLeAudioCodecLC3TypeAudioChannelAllocation) == 0)
660     return default_location;
661 
662   auto& vec = metadata.at(
663       bluetooth::le_audio::kLeAudioCodecLC3TypeAudioChannelAllocation);
664   return VEC_UINT8_TO_UINT32(vec);
665 }
666 
getSamplingFrequencyOrDefault(const std::map<uint8_t,std::vector<uint8_t>> & metadata,jint default_sampling_frequency)667 static jint getSamplingFrequencyOrDefault(
668     const std::map<uint8_t, std::vector<uint8_t>>& metadata,
669     jint default_sampling_frequency) {
670   if (metadata.count(bluetooth::le_audio::kLeAudioCodecLC3TypeSamplingFreq) ==
671       0)
672     return default_sampling_frequency;
673 
674   auto& vec =
675       metadata.at(bluetooth::le_audio::kLeAudioCodecLC3TypeSamplingFreq);
676   return (jint)(vec.data()[0]);
677 }
678 
getFrameDurationOrDefault(const std::map<uint8_t,std::vector<uint8_t>> & metadata,jint default_frame_duration)679 static jint getFrameDurationOrDefault(
680     const std::map<uint8_t, std::vector<uint8_t>>& metadata,
681     jint default_frame_duration) {
682   if (metadata.count(bluetooth::le_audio::kLeAudioCodecLC3TypeFrameDuration) ==
683       0)
684     return default_frame_duration;
685 
686   auto& vec =
687       metadata.at(bluetooth::le_audio::kLeAudioCodecLC3TypeFrameDuration);
688   return (jint)(vec.data()[0]);
689 }
690 
getOctetsPerFrameOrDefault(const std::map<uint8_t,std::vector<uint8_t>> & metadata,jint default_octets_per_frame)691 static jint getOctetsPerFrameOrDefault(
692     const std::map<uint8_t, std::vector<uint8_t>>& metadata,
693     jint default_octets_per_frame) {
694   if (metadata.count(bluetooth::le_audio::kLeAudioCodecLC3TypeOctetPerFrame) ==
695       0)
696     return default_octets_per_frame;
697 
698   auto& vec =
699       metadata.at(bluetooth::le_audio::kLeAudioCodecLC3TypeOctetPerFrame);
700   return VEC_UINT8_TO_UINT16(vec);
701 }
702 
prepareLeAudioCodecConfigMetadataObject(JNIEnv * env,const std::map<uint8_t,std::vector<uint8_t>> & metadata)703 jobject prepareLeAudioCodecConfigMetadataObject(
704     JNIEnv* env, const std::map<uint8_t, std::vector<uint8_t>>& metadata) {
705   jlong audio_location = getAudioLocationOrDefault(metadata, -1);
706   jint sampling_frequency = getSamplingFrequencyOrDefault(metadata, 0);
707   jint frame_duration = getFrameDurationOrDefault(metadata, -1);
708   jint octets_per_frame = getOctetsPerFrameOrDefault(metadata, 0);
709   ScopedLocalRef<jbyteArray> raw_metadata(env,
710                                           prepareRawLtvArray(env, metadata));
711   if (!raw_metadata.get()) {
712     LOG(ERROR) << "Failed to create raw metadata jbyteArray";
713     return nullptr;
714   }
715 
716   jobject obj = env->NewObject(
717       android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz,
718       android_bluetooth_BluetoothLeAudioCodecConfigMetadata.constructor,
719       audio_location, sampling_frequency, frame_duration, octets_per_frame,
720       raw_metadata.get());
721 
722   return obj;
723 }
724 
prepareLeBroadcastChannelObject(JNIEnv * env,const bluetooth::le_audio::BasicAudioAnnouncementBisConfig & bis_config)725 jobject prepareLeBroadcastChannelObject(
726     JNIEnv* env,
727     const bluetooth::le_audio::BasicAudioAnnouncementBisConfig& bis_config) {
728   ScopedLocalRef<jobject> meta_object(
729       env, prepareLeAudioCodecConfigMetadataObject(
730                env, bis_config.codec_specific_params));
731   if (!meta_object.get()) {
732     LOG(ERROR) << "Failed to create new metadata object for bis config";
733     return nullptr;
734   }
735 
736   jobject obj =
737       env->NewObject(android_bluetooth_BluetoothLeBroadcastChannel.clazz,
738                      android_bluetooth_BluetoothLeBroadcastChannel.constructor,
739                      false, bis_config.bis_index, meta_object.get());
740 
741   return obj;
742 }
743 
prepareLeAudioContentMetadataObject(JNIEnv * env,const std::map<uint8_t,std::vector<uint8_t>> & metadata)744 jobject prepareLeAudioContentMetadataObject(
745     JNIEnv* env, const std::map<uint8_t, std::vector<uint8_t>>& metadata) {
746   jstring program_info_str = nullptr;
747   if (metadata.count(bluetooth::le_audio::kLeAudioMetadataTypeProgramInfo)) {
748     program_info_str = env->NewStringUTF(
749         (const char*)(metadata
750                           .at(bluetooth::le_audio::
751                                   kLeAudioMetadataTypeProgramInfo)
752                           .data()));
753     if (!program_info_str) {
754       LOG(ERROR) << "Failed to create new preset name String for preset name";
755       return nullptr;
756     }
757   }
758 
759   jstring language_str = nullptr;
760   if (metadata.count(bluetooth::le_audio::kLeAudioMetadataTypeLanguage)) {
761     language_str = env->NewStringUTF(
762         (const char*)(metadata
763                           .at(bluetooth::le_audio::kLeAudioMetadataTypeLanguage)
764                           .data()));
765     if (!language_str) {
766       LOG(ERROR) << "Failed to create new preset name String for language";
767       return nullptr;
768     }
769   }
770 
771   // This can be nullptr
772   ScopedLocalRef<jbyteArray> raw_metadata(env,
773                                           prepareRawLtvArray(env, metadata));
774   if (!raw_metadata.get()) {
775     LOG(ERROR) << "Failed to create raw_metadata jbyteArray";
776     return nullptr;
777   }
778 
779   jobject obj = env->NewObject(
780       android_bluetooth_BluetoothLeAudioContentMetadata.clazz,
781       android_bluetooth_BluetoothLeAudioContentMetadata.constructor,
782       program_info_str, language_str, raw_metadata.get());
783 
784   if (program_info_str) {
785     env->DeleteLocalRef(program_info_str);
786   }
787 
788   if (language_str) {
789     env->DeleteLocalRef(language_str);
790   }
791 
792   return obj;
793 }
794 
prepareLeBroadcastChannelListObject(JNIEnv * env,const std::vector<bluetooth::le_audio::BasicAudioAnnouncementBisConfig> & bis_configs)795 jobject prepareLeBroadcastChannelListObject(
796     JNIEnv* env,
797     const std::vector<bluetooth::le_audio::BasicAudioAnnouncementBisConfig>&
798         bis_configs) {
799   jobject array = env->NewObject(java_util_ArrayList.clazz,
800                                  java_util_ArrayList.constructor);
801   if (!array) {
802     LOG(ERROR) << "Failed to create array for subgroups";
803     return nullptr;
804   }
805 
806   for (const auto& el : bis_configs) {
807     ScopedLocalRef<jobject> channel_obj(
808         env, prepareLeBroadcastChannelObject(env, el));
809     if (!channel_obj.get()) {
810       LOG(ERROR) << "Failed to create new channel object";
811       return nullptr;
812     }
813 
814     env->CallBooleanMethod(array, java_util_ArrayList.add, channel_obj.get());
815   }
816   return array;
817 }
818 
prepareLeBroadcastSubgroupObject(JNIEnv * env,const bluetooth::le_audio::BasicAudioAnnouncementSubgroup & subgroup)819 jobject prepareLeBroadcastSubgroupObject(
820     JNIEnv* env,
821     const bluetooth::le_audio::BasicAudioAnnouncementSubgroup& subgroup) {
822   // Serialize codec ID
823   jlong jlong_codec_id =
824       subgroup.codec_config.codec_id |
825       ((jlong)subgroup.codec_config.vendor_company_id << 16) |
826       ((jlong)subgroup.codec_config.vendor_codec_id << 32);
827 
828   ScopedLocalRef<jobject> codec_config_meta_obj(
829       env, prepareLeAudioCodecConfigMetadataObject(
830                env, subgroup.codec_config.codec_specific_params));
831   if (!codec_config_meta_obj.get()) {
832     LOG(ERROR) << "Failed to create new codec config metadata";
833     return nullptr;
834   }
835 
836   ScopedLocalRef<jobject> content_meta_obj(
837       env, prepareLeAudioContentMetadataObject(env, subgroup.metadata));
838   if (!content_meta_obj.get()) {
839     LOG(ERROR) << "Failed to create new codec config metadata";
840     return nullptr;
841   }
842 
843   ScopedLocalRef<jobject> channel_list_obj(
844       env, prepareLeBroadcastChannelListObject(env, subgroup.bis_configs));
845   if (!channel_list_obj.get()) {
846     LOG(ERROR) << "Failed to create new codec config metadata";
847     return nullptr;
848   }
849 
850   // Create the subgroup
851   return env->NewObject(
852       android_bluetooth_BluetoothLeBroadcastSubgroup.clazz,
853       android_bluetooth_BluetoothLeBroadcastSubgroup.constructor,
854       jlong_codec_id, codec_config_meta_obj.get(), content_meta_obj.get(),
855       channel_list_obj.get());
856 }
857 
prepareLeBroadcastSubgroupListObject(JNIEnv * env,const std::vector<bluetooth::le_audio::BasicAudioAnnouncementSubgroup> & subgroup_configs)858 jobject prepareLeBroadcastSubgroupListObject(
859     JNIEnv* env,
860     const std::vector<bluetooth::le_audio::BasicAudioAnnouncementSubgroup>&
861         subgroup_configs) {
862   jobject array = env->NewObject(java_util_ArrayList.clazz,
863                                  java_util_ArrayList.constructor);
864   if (!array) {
865     LOG(ERROR) << "Failed to create array for subgroups";
866     return nullptr;
867   }
868 
869   for (const auto& el : subgroup_configs) {
870     ScopedLocalRef<jobject> subgroup_obj(
871         env, prepareLeBroadcastSubgroupObject(env, el));
872     if (!subgroup_obj.get()) {
873       LOG(ERROR) << "Failed to create new subgroup object";
874       return nullptr;
875     }
876 
877     env->CallBooleanMethod(array, java_util_ArrayList.add, subgroup_obj.get());
878   }
879   return array;
880 }
881 
prepareBluetoothDeviceObject(JNIEnv * env,const RawAddress & addr,int addr_type)882 jobject prepareBluetoothDeviceObject(JNIEnv* env, const RawAddress& addr,
883                                      int addr_type) {
884   // The address string has to be uppercase or the BluetoothDevice constructor
885   // will treat it as invalid.
886   auto addr_str = addr.ToString();
887   std::transform(addr_str.begin(), addr_str.end(), addr_str.begin(),
888                  [](unsigned char c) { return std::toupper(c); });
889 
890   ScopedLocalRef<jstring> addr_jstr(env, env->NewStringUTF(addr_str.c_str()));
891   if (!addr_jstr.get()) {
892     LOG(ERROR) << "Failed to create new preset name String for preset name";
893     return nullptr;
894   }
895 
896   return env->NewObject(android_bluetooth_BluetoothDevice.clazz,
897                         android_bluetooth_BluetoothDevice.constructor,
898                         addr_jstr.get(), (jint)addr_type);
899 }
900 
prepareBluetoothLeBroadcastMetadataObject(JNIEnv * env,const bluetooth::le_audio::BroadcastMetadata & broadcast_metadata)901 jobject prepareBluetoothLeBroadcastMetadataObject(
902     JNIEnv* env,
903     const bluetooth::le_audio::BroadcastMetadata& broadcast_metadata) {
904   ScopedLocalRef<jobject> device_obj(
905       env, prepareBluetoothDeviceObject(env, broadcast_metadata.addr,
906                                         broadcast_metadata.addr_type));
907   if (!device_obj.get()) {
908     LOG(ERROR) << "Failed to create new BluetoothDevice";
909     return nullptr;
910   }
911 
912   ScopedLocalRef<jobject> subgroup_list_obj(
913       env,
914       prepareLeBroadcastSubgroupListObject(
915           env, broadcast_metadata.basic_audio_announcement.subgroup_configs));
916   if (!subgroup_list_obj.get()) {
917     LOG(ERROR) << "Failed to create new Subgroup array";
918     return nullptr;
919   }
920 
921   // Skip the leading null char bytes
922   int nativeCodeSize = 16;
923   int nativeCodeLeadingZeros = 0;
924   if (broadcast_metadata.broadcast_code) {
925     auto& nativeCode = broadcast_metadata.broadcast_code.value();
926     nativeCodeLeadingZeros =
927         std::find_if(nativeCode.cbegin(), nativeCode.cend(),
928                      [](int x) { return x != 0x00; }) -
929         nativeCode.cbegin();
930     nativeCodeSize = nativeCode.size() - nativeCodeLeadingZeros;
931   }
932 
933   ScopedLocalRef<jbyteArray> code(env, env->NewByteArray(nativeCodeSize));
934   if (!code.get()) {
935     LOG(ERROR) << "Failed to create new jbyteArray for the broadcast code";
936     return nullptr;
937   }
938 
939   if (broadcast_metadata.broadcast_code) {
940     env->SetByteArrayRegion(
941         code.get(), 0, nativeCodeSize,
942         (const jbyte*)broadcast_metadata.broadcast_code->data() +
943             nativeCodeLeadingZeros);
944     CHECK(!env->ExceptionCheck());
945   }
946 
947   ScopedLocalRef<jstring> broadcast_name(
948       env, env->NewStringUTF(broadcast_metadata.broadcast_name.c_str()));
949   if (!broadcast_name.get()) {
950     LOG(ERROR) << "Failed to create new broadcast name String";
951     return nullptr;
952   }
953 
954   jint audio_cfg_quality = 0;
955   if (broadcast_metadata.public_announcement.features &
956       bluetooth::le_audio::kLeAudioQualityStandard) {
957     // Set bit 0 for AUDIO_CONFIG_QUALITY_STANDARD
958     audio_cfg_quality |= 0x1 << bluetooth::le_audio::QUALITY_STANDARD;
959   }
960   if (broadcast_metadata.public_announcement.features &
961       bluetooth::le_audio::kLeAudioQualityHigh) {
962     // Set bit 1 for AUDIO_CONFIG_QUALITY_HIGH
963     audio_cfg_quality |= 0x1 << bluetooth::le_audio::QUALITY_HIGH;
964   }
965 
966   ScopedLocalRef<jobject> public_meta_obj(
967       env, prepareLeAudioContentMetadataObject(
968                env, broadcast_metadata.public_announcement.metadata));
969   if (!public_meta_obj.get()) {
970     LOG(ERROR) << "Failed to create new public metadata obj";
971     return nullptr;
972   }
973 
974   return env->NewObject(
975       android_bluetooth_BluetoothLeBroadcastMetadata.clazz,
976       android_bluetooth_BluetoothLeBroadcastMetadata.constructor,
977       (jint)broadcast_metadata.addr_type, device_obj.get(),
978       (jint)broadcast_metadata.adv_sid, (jint)broadcast_metadata.broadcast_id,
979       (jint)broadcast_metadata.pa_interval,
980       broadcast_metadata.broadcast_code ? true : false,
981       broadcast_metadata.is_public, broadcast_name.get(),
982       broadcast_metadata.broadcast_code ? code.get() : nullptr,
983       (jint)broadcast_metadata.basic_audio_announcement.presentation_delay,
984       audio_cfg_quality, public_meta_obj.get(), subgroup_list_obj.get());
985 }
986 
987 class LeAudioBroadcasterCallbacksImpl : public LeAudioBroadcasterCallbacks {
988  public:
989   ~LeAudioBroadcasterCallbacksImpl() = default;
990 
OnBroadcastCreated(uint32_t broadcast_id,bool success)991   void OnBroadcastCreated(uint32_t broadcast_id, bool success) override {
992     LOG(INFO) << __func__;
993 
994     std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
995     CallbackEnv sCallbackEnv(__func__);
996 
997     if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
998     sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj,
999                                  method_onBroadcastCreated, (jint)broadcast_id,
1000                                  success ? JNI_TRUE : JNI_FALSE);
1001   }
1002 
OnBroadcastDestroyed(uint32_t broadcast_id)1003   void OnBroadcastDestroyed(uint32_t broadcast_id) override {
1004     LOG(INFO) << __func__;
1005 
1006     std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
1007     CallbackEnv sCallbackEnv(__func__);
1008 
1009     if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
1010     sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj,
1011                                  method_onBroadcastDestroyed,
1012                                  (jint)broadcast_id);
1013   }
1014 
OnBroadcastStateChanged(uint32_t broadcast_id,BroadcastState state)1015   void OnBroadcastStateChanged(uint32_t broadcast_id,
1016                                BroadcastState state) override {
1017     LOG(INFO) << __func__;
1018 
1019     std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
1020     CallbackEnv sCallbackEnv(__func__);
1021 
1022     if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
1023     sCallbackEnv->CallVoidMethod(
1024         sBroadcasterCallbacksObj, method_onBroadcastStateChanged,
1025         (jint)broadcast_id,
1026         (jint) static_cast<std::underlying_type<BroadcastState>::type>(state));
1027   }
1028 
OnBroadcastMetadataChanged(uint32_t broadcast_id,const bluetooth::le_audio::BroadcastMetadata & broadcast_metadata)1029   void OnBroadcastMetadataChanged(uint32_t broadcast_id,
1030                                   const bluetooth::le_audio::BroadcastMetadata&
1031                                       broadcast_metadata) override {
1032     LOG(INFO) << __func__;
1033 
1034     std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
1035     CallbackEnv sCallbackEnv(__func__);
1036 
1037     ScopedLocalRef<jobject> metadata_obj(
1038         sCallbackEnv.get(), prepareBluetoothLeBroadcastMetadataObject(
1039                                 sCallbackEnv.get(), broadcast_metadata));
1040 
1041     if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
1042     sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj,
1043                                  method_onBroadcastMetadataChanged,
1044                                  (jint)broadcast_id, metadata_obj.get());
1045   }
1046 };
1047 
1048 static LeAudioBroadcasterCallbacksImpl sLeAudioBroadcasterCallbacks;
1049 
BroadcasterClassInitNative(JNIEnv * env,jclass clazz)1050 static void BroadcasterClassInitNative(JNIEnv* env, jclass clazz) {
1051   method_onBroadcastCreated =
1052       env->GetMethodID(clazz, "onBroadcastCreated", "(IZ)V");
1053   method_onBroadcastDestroyed =
1054       env->GetMethodID(clazz, "onBroadcastDestroyed", "(I)V");
1055   method_onBroadcastStateChanged =
1056       env->GetMethodID(clazz, "onBroadcastStateChanged", "(II)V");
1057   method_onBroadcastMetadataChanged =
1058       env->GetMethodID(clazz, "onBroadcastMetadataChanged",
1059                        "(ILandroid/bluetooth/BluetoothLeBroadcastMetadata;)V");
1060 
1061   jclass jniArrayListClass = env->FindClass("java/util/ArrayList");
1062   java_util_ArrayList.constructor =
1063       env->GetMethodID(jniArrayListClass, "<init>", "()V");
1064   java_util_ArrayList.add =
1065       env->GetMethodID(jniArrayListClass, "add", "(Ljava/lang/Object;)Z");
1066 
1067   jclass jniBluetoothLeAudioCodecConfigMetadataClass =
1068       env->FindClass("android/bluetooth/BluetoothLeAudioCodecConfigMetadata");
1069   android_bluetooth_BluetoothLeAudioCodecConfigMetadata.constructor =
1070       env->GetMethodID(jniBluetoothLeAudioCodecConfigMetadataClass, "<init>",
1071                        "(JIII[B)V");
1072 
1073   jclass jniBluetoothLeAudioContentMetadataClass =
1074       env->FindClass("android/bluetooth/BluetoothLeAudioContentMetadata");
1075   android_bluetooth_BluetoothLeAudioContentMetadata.constructor =
1076       env->GetMethodID(jniBluetoothLeAudioContentMetadataClass, "<init>",
1077                        "(Ljava/lang/String;Ljava/lang/String;[B)V");
1078 
1079   jclass jniBluetoothLeBroadcastChannelClass =
1080       env->FindClass("android/bluetooth/BluetoothLeBroadcastChannel");
1081   android_bluetooth_BluetoothLeBroadcastChannel.constructor = env->GetMethodID(
1082       jniBluetoothLeBroadcastChannelClass, "<init>",
1083       "(ZILandroid/bluetooth/BluetoothLeAudioCodecConfigMetadata;)V");
1084 
1085   jclass jniBluetoothLeBroadcastSubgroupClass =
1086       env->FindClass("android/bluetooth/BluetoothLeBroadcastSubgroup");
1087   android_bluetooth_BluetoothLeBroadcastSubgroup.constructor = env->GetMethodID(
1088       jniBluetoothLeBroadcastSubgroupClass, "<init>",
1089       "(JLandroid/bluetooth/BluetoothLeAudioCodecConfigMetadata;"
1090       "Landroid/bluetooth/BluetoothLeAudioContentMetadata;"
1091       "Ljava/util/List;)V");
1092 
1093   jclass jniBluetoothDeviceClass =
1094       env->FindClass("android/bluetooth/BluetoothDevice");
1095   android_bluetooth_BluetoothDevice.constructor = env->GetMethodID(
1096       jniBluetoothDeviceClass, "<init>", "(Ljava/lang/String;I)V");
1097 
1098   jclass jniBluetoothLeBroadcastMetadataClass =
1099       env->FindClass("android/bluetooth/BluetoothLeBroadcastMetadata");
1100   android_bluetooth_BluetoothLeBroadcastMetadata.constructor = env->GetMethodID(
1101       jniBluetoothLeBroadcastMetadataClass, "<init>",
1102       "(ILandroid/bluetooth/BluetoothDevice;IIIZZLjava/lang/String;"
1103       "[BIILandroid/bluetooth/BluetoothLeAudioContentMetadata;"
1104       "Ljava/util/List;)V");
1105 }
1106 
BroadcasterInitNative(JNIEnv * env,jobject object)1107 static void BroadcasterInitNative(JNIEnv* env, jobject object) {
1108   std::unique_lock<std::shared_timed_mutex> interface_lock(
1109       sBroadcasterInterfaceMutex);
1110   std::unique_lock<std::shared_timed_mutex> callbacks_lock(
1111       sBroadcasterCallbacksMutex);
1112 
1113   const bt_interface_t* btInf = getBluetoothInterface();
1114   if (btInf == nullptr) {
1115     LOG(ERROR) << "Bluetooth module is not loaded";
1116     return;
1117   }
1118 
1119   android_bluetooth_BluetoothDevice.clazz = (jclass)env->NewGlobalRef(
1120       env->FindClass("android/bluetooth/BluetoothDevice"));
1121   if (android_bluetooth_BluetoothDevice.clazz == nullptr) {
1122     LOG(ERROR) << "Failed to allocate Global Ref for BluetoothDevice class";
1123     return;
1124   }
1125 
1126   java_util_ArrayList.clazz =
1127       (jclass)env->NewGlobalRef(env->FindClass("java/util/ArrayList"));
1128   if (java_util_ArrayList.clazz == nullptr) {
1129     LOG(ERROR) << "Failed to allocate Global Ref for ArrayList class";
1130     return;
1131   }
1132 
1133   android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz =
1134       (jclass)env->NewGlobalRef(env->FindClass(
1135           "android/bluetooth/BluetoothLeAudioCodecConfigMetadata"));
1136   if (android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz == nullptr) {
1137     LOG(ERROR) << "Failed to allocate Global Ref for "
1138                   "BluetoothLeAudioCodecConfigMetadata class";
1139     return;
1140   }
1141 
1142   android_bluetooth_BluetoothLeAudioContentMetadata.clazz =
1143       (jclass)env->NewGlobalRef(
1144           env->FindClass("android/bluetooth/BluetoothLeAudioContentMetadata"));
1145   if (android_bluetooth_BluetoothLeAudioContentMetadata.clazz == nullptr) {
1146     LOG(ERROR) << "Failed to allocate Global Ref for "
1147                   "BluetoothLeAudioContentMetadata class";
1148     return;
1149   }
1150 
1151   android_bluetooth_BluetoothLeBroadcastSubgroup.clazz =
1152       (jclass)env->NewGlobalRef(
1153           env->FindClass("android/bluetooth/BluetoothLeBroadcastSubgroup"));
1154   if (android_bluetooth_BluetoothLeBroadcastSubgroup.clazz == nullptr) {
1155     LOG(ERROR) << "Failed to allocate Global Ref for "
1156                   "BluetoothLeBroadcastSubgroup class";
1157     return;
1158   }
1159 
1160   android_bluetooth_BluetoothLeBroadcastChannel.clazz =
1161       (jclass)env->NewGlobalRef(
1162           env->FindClass("android/bluetooth/BluetoothLeBroadcastChannel"));
1163   if (android_bluetooth_BluetoothLeBroadcastChannel.clazz == nullptr) {
1164     LOG(ERROR) << "Failed to allocate Global Ref for "
1165                   "BluetoothLeBroadcastChannel class";
1166     return;
1167   }
1168 
1169   android_bluetooth_BluetoothLeBroadcastMetadata.clazz =
1170       (jclass)env->NewGlobalRef(
1171           env->FindClass("android/bluetooth/BluetoothLeBroadcastMetadata"));
1172   if (android_bluetooth_BluetoothLeBroadcastMetadata.clazz == nullptr) {
1173     LOG(ERROR) << "Failed to allocate Global Ref for "
1174                   "BluetoothLeBroadcastMetadata class";
1175     return;
1176   }
1177 
1178   if (sBroadcasterCallbacksObj != nullptr) {
1179     LOG(INFO) << "Cleaning up LeAudio Broadcaster callback object";
1180     env->DeleteGlobalRef(sBroadcasterCallbacksObj);
1181     sBroadcasterCallbacksObj = nullptr;
1182   }
1183 
1184   if ((sBroadcasterCallbacksObj = env->NewGlobalRef(object)) == nullptr) {
1185     LOG(ERROR)
1186         << "Failed to allocate Global Ref for LeAudio Broadcaster Callbacks";
1187     return;
1188   }
1189 
1190   sLeAudioBroadcasterInterface =
1191       (LeAudioBroadcasterInterface*)btInf->get_profile_interface(
1192           BT_PROFILE_LE_AUDIO_BROADCASTER_ID);
1193   if (sLeAudioBroadcasterInterface == nullptr) {
1194     LOG(ERROR) << "Failed to get Bluetooth LeAudio Broadcaster Interface";
1195     return;
1196   }
1197 
1198   sLeAudioBroadcasterInterface->Initialize(&sLeAudioBroadcasterCallbacks);
1199 }
1200 
BroadcasterStopNative(JNIEnv * env,jobject object)1201 static void BroadcasterStopNative(JNIEnv* env, jobject object) {
1202   std::unique_lock<std::shared_timed_mutex> interface_lock(
1203       sBroadcasterInterfaceMutex);
1204 
1205   const bt_interface_t* btInf = getBluetoothInterface();
1206   if (btInf == nullptr) {
1207     LOG(ERROR) << "Bluetooth module is not loaded";
1208     return;
1209   }
1210 
1211   if (sLeAudioBroadcasterInterface != nullptr)
1212     sLeAudioBroadcasterInterface->Stop();
1213 }
1214 
BroadcasterCleanupNative(JNIEnv * env,jobject object)1215 static void BroadcasterCleanupNative(JNIEnv* env, jobject object) {
1216   std::unique_lock<std::shared_timed_mutex> interface_lock(
1217       sBroadcasterInterfaceMutex);
1218   std::unique_lock<std::shared_timed_mutex> callbacks_lock(
1219       sBroadcasterCallbacksMutex);
1220 
1221   const bt_interface_t* btInf = getBluetoothInterface();
1222   if (btInf == nullptr) {
1223     LOG(ERROR) << "Bluetooth module is not loaded";
1224     return;
1225   }
1226 
1227   env->DeleteGlobalRef(java_util_ArrayList.clazz);
1228   java_util_ArrayList.clazz = nullptr;
1229 
1230   env->DeleteGlobalRef(android_bluetooth_BluetoothDevice.clazz);
1231   android_bluetooth_BluetoothDevice.clazz = nullptr;
1232 
1233   env->DeleteGlobalRef(
1234       android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz);
1235   android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz = nullptr;
1236 
1237   env->DeleteGlobalRef(android_bluetooth_BluetoothLeAudioContentMetadata.clazz);
1238   android_bluetooth_BluetoothLeAudioContentMetadata.clazz = nullptr;
1239 
1240   env->DeleteGlobalRef(android_bluetooth_BluetoothLeBroadcastSubgroup.clazz);
1241   android_bluetooth_BluetoothLeBroadcastSubgroup.clazz = nullptr;
1242 
1243   env->DeleteGlobalRef(android_bluetooth_BluetoothLeBroadcastChannel.clazz);
1244   android_bluetooth_BluetoothLeBroadcastChannel.clazz = nullptr;
1245 
1246   env->DeleteGlobalRef(android_bluetooth_BluetoothLeBroadcastMetadata.clazz);
1247   android_bluetooth_BluetoothLeBroadcastMetadata.clazz = nullptr;
1248 
1249   if (sLeAudioBroadcasterInterface != nullptr) {
1250     sLeAudioBroadcasterInterface->Cleanup();
1251     sLeAudioBroadcasterInterface = nullptr;
1252   }
1253 
1254   if (sBroadcasterCallbacksObj != nullptr) {
1255     env->DeleteGlobalRef(sBroadcasterCallbacksObj);
1256     sBroadcasterCallbacksObj = nullptr;
1257   }
1258 }
1259 
convertToDataVectors(JNIEnv * env,jobjectArray dataArray)1260 std::vector<std::vector<uint8_t>> convertToDataVectors(JNIEnv* env,
1261                                                        jobjectArray dataArray) {
1262   jsize arraySize = env->GetArrayLength(dataArray);
1263   std::vector<std::vector<uint8_t>> res(arraySize);
1264 
1265   for (int i = 0; i < arraySize; ++i) {
1266     jbyteArray rowData = (jbyteArray)env->GetObjectArrayElement(dataArray, i);
1267     jsize dataSize = env->GetArrayLength(rowData);
1268     std::vector<uint8_t>& rowVector = res[i];
1269     rowVector.resize(dataSize);
1270     env->GetByteArrayRegion(rowData, 0, dataSize,
1271                             reinterpret_cast<jbyte*>(rowVector.data()));
1272     env->DeleteLocalRef(rowData);
1273   }
1274   return res;
1275 }
1276 
CreateBroadcastNative(JNIEnv * env,jobject object,jboolean isPublic,jstring broadcastName,jbyteArray broadcast_code,jbyteArray publicMetadata,jintArray qualityArray,jobjectArray metadataArray)1277 static void CreateBroadcastNative(JNIEnv* env, jobject object,
1278                                   jboolean isPublic, jstring broadcastName,
1279                                   jbyteArray broadcast_code,
1280                                   jbyteArray publicMetadata,
1281                                   jintArray qualityArray,
1282                                   jobjectArray metadataArray) {
1283   LOG(INFO) << __func__;
1284   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1285   if (!sLeAudioBroadcasterInterface) return;
1286 
1287   std::array<uint8_t, 16> code_array{0};
1288   if (broadcast_code) {
1289     jsize size = env->GetArrayLength(broadcast_code);
1290     if (size > 16) {
1291       ALOGE("%s: broadcast code to long", __func__);
1292       return;
1293     }
1294 
1295     // Padding with zeros on MSB positions if code is shorter than 16 octets
1296     env->GetByteArrayRegion(broadcast_code, 0, size, (jbyte*)code_array.data());
1297   }
1298 
1299   const char* broadcast_name = nullptr;
1300   if (broadcastName) {
1301     broadcast_name = env->GetStringUTFChars(broadcastName, nullptr);
1302   }
1303 
1304   jbyte* public_meta = nullptr;
1305   if (publicMetadata) {
1306     public_meta = env->GetByteArrayElements(publicMetadata, nullptr);
1307   }
1308 
1309   jint* quality_array = nullptr;
1310   if (qualityArray) {
1311     quality_array = env->GetIntArrayElements(qualityArray, nullptr);
1312   }
1313 
1314   sLeAudioBroadcasterInterface->CreateBroadcast(
1315       isPublic, broadcast_name ? broadcast_name : "",
1316       broadcast_code ? std::optional<std::array<uint8_t, 16>>(code_array)
1317                      : std::nullopt,
1318       public_meta ? std::vector<uint8_t>(
1319                         public_meta, public_meta + env->GetArrayLength(publicMetadata))
1320                   : std::vector<uint8_t>(),
1321       quality_array ? std::vector<uint8_t>(
1322                         quality_array, quality_array + env->GetArrayLength(qualityArray))
1323                   : std::vector<uint8_t>(),
1324       convertToDataVectors(env, metadataArray));
1325 
1326   if (broadcast_name) env->ReleaseStringUTFChars(broadcastName, broadcast_name);
1327   if (public_meta) env->ReleaseByteArrayElements(publicMetadata, public_meta, 0);
1328   if (quality_array) env->ReleaseIntArrayElements(qualityArray, quality_array, 0);
1329 }
1330 
UpdateMetadataNative(JNIEnv * env,jobject object,jint broadcast_id,jstring broadcastName,jbyteArray publicMetadata,jobjectArray metadataArray)1331 static void UpdateMetadataNative(JNIEnv* env, jobject object, jint broadcast_id,
1332                                  jstring broadcastName,
1333                                  jbyteArray publicMetadata,
1334                                  jobjectArray metadataArray) {
1335   const char* broadcast_name = nullptr;
1336   if (broadcastName) {
1337     broadcast_name = env->GetStringUTFChars(broadcastName, nullptr);
1338   }
1339 
1340   jbyte* public_meta = nullptr;
1341   if (publicMetadata) {
1342     public_meta = env->GetByteArrayElements(publicMetadata, nullptr);
1343   }
1344 
1345   sLeAudioBroadcasterInterface->UpdateMetadata(
1346       broadcast_id, broadcast_name ? broadcast_name : "",
1347       public_meta
1348           ? std::vector<uint8_t>(
1349                 public_meta, public_meta + env->GetArrayLength(publicMetadata))
1350           : std::vector<uint8_t>(),
1351       convertToDataVectors(env, metadataArray));
1352 
1353   if (broadcast_name) env->ReleaseStringUTFChars(broadcastName, broadcast_name);
1354   if (public_meta) env->ReleaseByteArrayElements(publicMetadata, public_meta, 0);
1355 }
1356 
StartBroadcastNative(JNIEnv * env,jobject object,jint broadcast_id)1357 static void StartBroadcastNative(JNIEnv* env, jobject object,
1358                                  jint broadcast_id) {
1359   LOG(INFO) << __func__;
1360   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1361   if (!sLeAudioBroadcasterInterface) return;
1362   sLeAudioBroadcasterInterface->StartBroadcast(broadcast_id);
1363 }
1364 
StopBroadcastNative(JNIEnv * env,jobject object,jint broadcast_id)1365 static void StopBroadcastNative(JNIEnv* env, jobject object,
1366                                 jint broadcast_id) {
1367   LOG(INFO) << __func__;
1368   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1369   if (!sLeAudioBroadcasterInterface) return;
1370   sLeAudioBroadcasterInterface->StopBroadcast(broadcast_id);
1371 }
1372 
PauseBroadcastNative(JNIEnv * env,jobject object,jint broadcast_id)1373 static void PauseBroadcastNative(JNIEnv* env, jobject object,
1374                                  jint broadcast_id) {
1375   LOG(INFO) << __func__;
1376   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1377   if (!sLeAudioBroadcasterInterface) return;
1378   sLeAudioBroadcasterInterface->PauseBroadcast(broadcast_id);
1379 }
1380 
DestroyBroadcastNative(JNIEnv * env,jobject object,jint broadcast_id)1381 static void DestroyBroadcastNative(JNIEnv* env, jobject object,
1382                                    jint broadcast_id) {
1383   LOG(INFO) << __func__;
1384   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1385   if (!sLeAudioBroadcasterInterface) return;
1386   sLeAudioBroadcasterInterface->DestroyBroadcast(broadcast_id);
1387 }
1388 
getBroadcastMetadataNative(JNIEnv * env,jobject object,jint broadcast_id)1389 static void getBroadcastMetadataNative(JNIEnv* env, jobject object,
1390                                        jint broadcast_id) {
1391   LOG(INFO) << __func__;
1392   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1393   if (!sLeAudioBroadcasterInterface) return;
1394   sLeAudioBroadcasterInterface->GetBroadcastMetadata(broadcast_id);
1395 }
1396 
1397 static JNINativeMethod sBroadcasterMethods[] = {
1398     {"classInitNative", "()V", (void*)BroadcasterClassInitNative},
1399     {"initNative", "()V", (void*)BroadcasterInitNative},
1400     {"stopNative", "()V", (void*)BroadcasterStopNative},
1401     {"cleanupNative", "()V", (void*)BroadcasterCleanupNative},
1402     {"createBroadcastNative", "(ZLjava/lang/String;[B[B[I[[B)V",
1403      (void*)CreateBroadcastNative},
1404     {"updateMetadataNative", "(ILjava/lang/String;[B[[B)V",
1405      (void*)UpdateMetadataNative},
1406     {"startBroadcastNative", "(I)V", (void*)StartBroadcastNative},
1407     {"stopBroadcastNative", "(I)V", (void*)StopBroadcastNative},
1408     {"pauseBroadcastNative", "(I)V", (void*)PauseBroadcastNative},
1409     {"destroyBroadcastNative", "(I)V", (void*)DestroyBroadcastNative},
1410     {"getBroadcastMetadataNative", "(I)V", (void*)getBroadcastMetadataNative},
1411 };
1412 
register_com_android_bluetooth_le_audio(JNIEnv * env)1413 int register_com_android_bluetooth_le_audio(JNIEnv* env) {
1414   int register_success = jniRegisterNativeMethods(
1415       env, "com/android/bluetooth/le_audio/LeAudioNativeInterface", sMethods,
1416       NELEM(sMethods));
1417   return register_success &
1418          jniRegisterNativeMethods(
1419              env,
1420              "com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterface",
1421              sBroadcasterMethods, NELEM(sBroadcasterMethods));
1422 }
1423 }  // namespace android
1424