1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "BluetoothAvrcpControllerJni"
18 
19 #include <string.h>
20 
21 #include <shared_mutex>
22 
23 #include "com_android_bluetooth.h"
24 #include "hardware/bt_rc.h"
25 
26 namespace android {
27 static jmethodID method_onConnectionStateChanged;
28 static jmethodID method_handleplayerappsetting;
29 static jmethodID method_handleplayerappsettingchanged;
30 static jmethodID method_handleSetAbsVolume;
31 static jmethodID method_handleRegisterNotificationAbsVol;
32 static jmethodID method_handletrackchanged;
33 static jmethodID method_handleplaypositionchanged;
34 static jmethodID method_handleplaystatuschanged;
35 static jmethodID method_handleGetFolderItemsRsp;
36 static jmethodID method_handleGetPlayerItemsRsp;
37 static jmethodID method_createFromNativeMediaItem;
38 static jmethodID method_createFromNativeFolderItem;
39 static jmethodID method_createFromNativePlayerItem;
40 static jmethodID method_handleChangeFolderRsp;
41 static jmethodID method_handleSetBrowsedPlayerRsp;
42 static jmethodID method_handleSetAddressedPlayerRsp;
43 static jmethodID method_handleAddressedPlayerChanged;
44 static jmethodID method_handleNowPlayingContentChanged;
45 static jmethodID method_onAvailablePlayerChanged;
46 static jmethodID method_getRcPsm;
47 
48 static jclass class_AvrcpControllerNativeInterface;
49 static jclass class_AvrcpItem;
50 static jclass class_AvrcpPlayer;
51 
52 static const btrc_ctrl_interface_t* sBluetoothAvrcpInterface = NULL;
53 static jobject sCallbacksObj = NULL;
54 static std::shared_timed_mutex sCallbacks_mutex;
55 
btavrcp_passthrough_response_callback(const RawAddress &,int id,int pressed)56 static void btavrcp_passthrough_response_callback(
57     const RawAddress& /* bd_addr */, int id, int pressed) {
58   log::verbose("id: {}, pressed: {} --- Not implemented", id, pressed);
59 }
60 
btavrcp_groupnavigation_response_callback(int id,int pressed)61 static void btavrcp_groupnavigation_response_callback(int id, int pressed) {
62   log::verbose("id: {}, pressed: {} --- Not implemented", id, pressed);
63 }
64 
btavrcp_connection_state_callback(bool rc_connect,bool br_connect,const RawAddress & bd_addr)65 static void btavrcp_connection_state_callback(bool rc_connect, bool br_connect,
66                                               const RawAddress& bd_addr) {
67   log::info("conn state: rc: {} br: {}", rc_connect, br_connect);
68   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
69   CallbackEnv sCallbackEnv(__func__);
70   if (!sCallbackEnv.valid()) return;
71   if (!sCallbacksObj) {
72     log::error("sCallbacksObj is null");
73     return;
74   }
75 
76   ScopedLocalRef<jbyteArray> addr(
77       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
78   if (!addr.get()) {
79     log::error("Failed to allocate a new byte array");
80     return;
81   }
82 
83   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
84                                    (jbyte*)bd_addr.address);
85   sCallbackEnv->CallVoidMethod(sCallbacksObj, method_onConnectionStateChanged,
86                                (jboolean)rc_connect, (jboolean)br_connect,
87                                addr.get());
88 }
89 
btavrcp_get_rcfeatures_callback(const RawAddress &,int)90 static void btavrcp_get_rcfeatures_callback(const RawAddress& /* bd_addr */,
91                                             int /* features */) {
92   log::verbose("--- Not implemented");
93 }
btavrcp_setplayerapplicationsetting_rsp_callback(const RawAddress &,uint8_t)94 static void btavrcp_setplayerapplicationsetting_rsp_callback(
95     const RawAddress& /* bd_addr */, uint8_t /* accepted */) {
96   log::verbose("--- Not implemented");
97 }
98 
btavrcp_playerapplicationsetting_callback(const RawAddress & bd_addr,uint8_t num_attr,btrc_player_app_attr_t * app_attrs,uint8_t,btrc_player_app_ext_attr_t *)99 static void btavrcp_playerapplicationsetting_callback(
100     const RawAddress& bd_addr, uint8_t num_attr,
101     btrc_player_app_attr_t* app_attrs, uint8_t /* num_ext_attr */,
102     btrc_player_app_ext_attr_t* /* ext_attrs */) {
103   log::info("");
104   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
105   CallbackEnv sCallbackEnv(__func__);
106   if (!sCallbackEnv.valid()) return;
107   if (!sCallbacksObj) {
108     log::error("sCallbacksObj is null");
109     return;
110   }
111 
112   ScopedLocalRef<jbyteArray> addr(
113       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
114   if (!addr.get()) {
115     log::error("Failed to allocate a new byte array");
116     return;
117   }
118   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
119                                    (jbyte*)&bd_addr.address);
120   /* TODO ext attrs
121    * Flattening defined attributes: <id,num_values,values[]>
122    */
123   jint arraylen = 0;
124   for (int i = 0; i < num_attr; i++) {
125     /*2 bytes for id and num */
126     arraylen += 2 + app_attrs[i].num_val;
127   }
128   log::verbose("arraylen {}", arraylen);
129 
130   ScopedLocalRef<jbyteArray> playerattribs(
131       sCallbackEnv.get(), sCallbackEnv->NewByteArray(arraylen));
132   if (!playerattribs.get()) {
133     log::error("Failed to allocate a new byte array");
134     return;
135   }
136 
137   for (int i = 0, k = 0; (i < num_attr) && (k < arraylen); i++) {
138     sCallbackEnv->SetByteArrayRegion(playerattribs.get(), k, 1,
139                                      (jbyte*)&(app_attrs[i].attr_id));
140     k++;
141     sCallbackEnv->SetByteArrayRegion(playerattribs.get(), k, 1,
142                                      (jbyte*)&(app_attrs[i].num_val));
143     k++;
144     sCallbackEnv->SetByteArrayRegion(playerattribs.get(), k,
145                                      app_attrs[i].num_val,
146                                      (jbyte*)(app_attrs[i].attr_val));
147     k = k + app_attrs[i].num_val;
148   }
149   sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleplayerappsetting,
150                                addr.get(), playerattribs.get(), (jint)arraylen);
151 }
152 
btavrcp_playerapplicationsetting_changed_callback(const RawAddress & bd_addr,const btrc_player_settings_t & vals)153 static void btavrcp_playerapplicationsetting_changed_callback(
154     const RawAddress& bd_addr, const btrc_player_settings_t& vals) {
155   log::info("");
156   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
157   CallbackEnv sCallbackEnv(__func__);
158   if (!sCallbackEnv.valid()) return;
159   if (!sCallbacksObj) {
160     log::error("sCallbacksObj is null");
161     return;
162   }
163 
164   ScopedLocalRef<jbyteArray> addr(
165       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
166   if (!addr.get()) {
167     log::error("Failed to allocate a new byte array");
168     return;
169   }
170   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
171                                    (jbyte*)&bd_addr.address);
172 
173   int arraylen = vals.num_attr * 2;
174   ScopedLocalRef<jbyteArray> playerattribs(
175       sCallbackEnv.get(), sCallbackEnv->NewByteArray(arraylen));
176   if (!playerattribs.get()) {
177     log::error("Fail to new jbyteArray playerattribs");
178     return;
179   }
180   /*
181    * Flatening format: <id,val>
182    */
183   for (int i = 0, k = 0; (i < vals.num_attr) && (k < arraylen); i++) {
184     sCallbackEnv->SetByteArrayRegion(playerattribs.get(), k, 1,
185                                      (jbyte*)&(vals.attr_ids[i]));
186     k++;
187     sCallbackEnv->SetByteArrayRegion(playerattribs.get(), k, 1,
188                                      (jbyte*)&(vals.attr_values[i]));
189     k++;
190   }
191   sCallbackEnv->CallVoidMethod(sCallbacksObj,
192                                method_handleplayerappsettingchanged, addr.get(),
193                                playerattribs.get(), (jint)arraylen);
194 }
195 
btavrcp_set_abs_vol_cmd_callback(const RawAddress & bd_addr,uint8_t abs_vol,uint8_t label)196 static void btavrcp_set_abs_vol_cmd_callback(const RawAddress& bd_addr,
197                                              uint8_t abs_vol, uint8_t label) {
198   log::info("");
199   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
200   CallbackEnv sCallbackEnv(__func__);
201   if (!sCallbackEnv.valid()) return;
202   if (!sCallbacksObj) {
203     log::error("sCallbacksObj is null");
204     return;
205   }
206 
207   ScopedLocalRef<jbyteArray> addr(
208       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
209   if (!addr.get()) {
210     log::error("Failed to allocate a new byte array");
211     return;
212   }
213 
214   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
215                                    (jbyte*)&bd_addr.address);
216   sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleSetAbsVolume,
217                                addr.get(), (jbyte)abs_vol, (jbyte)label);
218 }
219 
btavrcp_register_notification_absvol_callback(const RawAddress & bd_addr,uint8_t label)220 static void btavrcp_register_notification_absvol_callback(
221     const RawAddress& bd_addr, uint8_t label) {
222   log::info("");
223   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
224   CallbackEnv sCallbackEnv(__func__);
225   if (!sCallbackEnv.valid()) return;
226   if (!sCallbacksObj) {
227     log::error("sCallbacksObj is null");
228     return;
229   }
230 
231   ScopedLocalRef<jbyteArray> addr(
232       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
233   if (!addr.get()) {
234     log::error("Failed to allocate a new byte array");
235     return;
236   }
237 
238   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
239                                    (jbyte*)&bd_addr.address);
240   sCallbackEnv->CallVoidMethod(sCallbacksObj,
241                                method_handleRegisterNotificationAbsVol,
242                                addr.get(), (jbyte)label);
243 }
244 
btavrcp_track_changed_callback(const RawAddress & bd_addr,uint8_t num_attr,btrc_element_attr_val_t * p_attrs)245 static void btavrcp_track_changed_callback(const RawAddress& bd_addr,
246                                            uint8_t num_attr,
247                                            btrc_element_attr_val_t* p_attrs) {
248   /*
249    * byteArray will be formatted like this: id,len,string
250    * Assuming text feild to be null terminated.
251    */
252   log::info("");
253   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
254   CallbackEnv sCallbackEnv(__func__);
255   if (!sCallbackEnv.valid()) return;
256   if (!sCallbacksObj) {
257     log::error("sCallbacksObj is null");
258     return;
259   }
260 
261   ScopedLocalRef<jbyteArray> addr(
262       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
263   if (!addr.get()) {
264     log::error("Failed to allocate a new byte array");
265     return;
266   }
267 
268   ScopedLocalRef<jintArray> attribIds(sCallbackEnv.get(),
269                                       sCallbackEnv->NewIntArray(num_attr));
270   if (!attribIds.get()) {
271     log::error("failed to set new array for attribIds");
272     return;
273   }
274   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
275                                    (jbyte*)&bd_addr.address);
276 
277   jclass strclazz = sCallbackEnv->FindClass("java/lang/String");
278   ScopedLocalRef<jobjectArray> stringArray(
279       sCallbackEnv.get(),
280       sCallbackEnv->NewObjectArray((jint)num_attr, strclazz, 0));
281   if (!stringArray.get()) {
282     log::error("failed to get String array");
283     return;
284   }
285 
286   for (jint i = 0; i < num_attr; i++) {
287     ScopedLocalRef<jstring> str(
288         sCallbackEnv.get(),
289         sCallbackEnv->NewStringUTF((char*)(p_attrs[i].text)));
290     if (!str.get()) {
291       log::error("Unable to get str");
292       return;
293     }
294     sCallbackEnv->SetIntArrayRegion(attribIds.get(), i, 1,
295                                     (jint*)&(p_attrs[i].attr_id));
296     sCallbackEnv->SetObjectArrayElement(stringArray.get(), i, str.get());
297   }
298 
299   sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handletrackchanged,
300                                addr.get(), (jbyte)(num_attr), attribIds.get(),
301                                stringArray.get());
302 }
303 
btavrcp_play_position_changed_callback(const RawAddress & bd_addr,uint32_t song_len,uint32_t song_pos)304 static void btavrcp_play_position_changed_callback(const RawAddress& bd_addr,
305                                                    uint32_t song_len,
306                                                    uint32_t song_pos) {
307   log::info("");
308   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
309   CallbackEnv sCallbackEnv(__func__);
310   if (!sCallbackEnv.valid()) return;
311   if (!sCallbacksObj) {
312     log::error("sCallbacksObj is null");
313     return;
314   }
315 
316   ScopedLocalRef<jbyteArray> addr(
317       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
318   if (!addr.get()) {
319     log::error("Failed to allocate a new byte array");
320     return;
321   }
322   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
323                                    (jbyte*)&bd_addr.address);
324   sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleplaypositionchanged,
325                                addr.get(), (jint)(song_len), (jint)song_pos);
326 }
327 
btavrcp_play_status_changed_callback(const RawAddress & bd_addr,btrc_play_status_t play_status)328 static void btavrcp_play_status_changed_callback(
329     const RawAddress& bd_addr, btrc_play_status_t play_status) {
330   log::info("");
331   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
332   CallbackEnv sCallbackEnv(__func__);
333   if (!sCallbackEnv.valid()) return;
334   if (!sCallbacksObj) {
335     log::error("sCallbacksObj is null");
336     return;
337   }
338 
339   ScopedLocalRef<jbyteArray> addr(
340       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
341   if (!addr.get()) {
342     log::error("Failed to allocate a new byte array");
343     return;
344   }
345   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
346                                    (jbyte*)&bd_addr.address);
347   sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleplaystatuschanged,
348                                addr.get(), (jbyte)play_status);
349 }
350 
btavrcp_get_folder_items_callback(const RawAddress & bd_addr,btrc_status_t status,const btrc_folder_items_t * folder_items,uint8_t count)351 static void btavrcp_get_folder_items_callback(
352     const RawAddress& bd_addr, btrc_status_t status,
353     const btrc_folder_items_t* folder_items, uint8_t count) {
354   /* Folder items are list of items that can be either BTRC_ITEM_PLAYER
355    * BTRC_ITEM_MEDIA, BTRC_ITEM_FOLDER. Here we translate them to their java
356    * counterparts by calling the java constructor for each of the items.
357    */
358   log::verbose("count {}", count);
359   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
360   CallbackEnv sCallbackEnv(__func__);
361   if (!sCallbackEnv.valid()) return;
362   if (!sCallbacksObj) {
363     log::error("sCallbacksObj is null");
364     return;
365   }
366 
367   ScopedLocalRef<jbyteArray> addr(
368       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
369   if (!addr.get()) {
370     log::error("Failed to allocate a new byte array");
371     return;
372   }
373 
374   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
375                                    (jbyte*)&bd_addr.address);
376 
377   // Inspect if the first element is a folder/item or player listing. They are
378   // always exclusive.
379   bool isPlayerListing =
380       count > 0 && (folder_items[0].item_type == BTRC_ITEM_PLAYER);
381 
382   // Initialize arrays for Folder OR Player listing.
383   ScopedLocalRef<jobjectArray> itemArray(sCallbackEnv.get(), NULL);
384   if (isPlayerListing) {
385     itemArray.reset(
386         sCallbackEnv->NewObjectArray((jint)count, class_AvrcpPlayer, 0));
387   } else {
388     itemArray.reset(sCallbackEnv->NewObjectArray(
389         (jint)count, class_AvrcpItem, 0));
390   }
391   if (!itemArray.get()) {
392     log::error("itemArray allocation failed.");
393     return;
394   }
395   for (int i = 0; i < count; i++) {
396     const btrc_folder_items_t* item = &(folder_items[i]);
397     log::verbose("item type {}", item->item_type);
398     switch (item->item_type) {
399       case BTRC_ITEM_MEDIA: {
400         // Parse name
401         ScopedLocalRef<jstring> mediaName(
402             sCallbackEnv.get(),
403             sCallbackEnv->NewStringUTF((const char*)item->media.name));
404         if (!mediaName.get()) {
405           log::error("can't allocate media name string!");
406           return;
407         }
408         // Parse UID
409         long long uid = *(long long*)item->media.uid;
410         // Parse Attrs
411         ScopedLocalRef<jintArray> attrIdArray(
412             sCallbackEnv.get(),
413             sCallbackEnv->NewIntArray(item->media.num_attrs));
414         if (!attrIdArray.get()) {
415           log::error("can't allocate attr id array!");
416           return;
417         }
418         ScopedLocalRef<jobjectArray> attrValArray(
419             sCallbackEnv.get(),
420             sCallbackEnv->NewObjectArray(
421                 item->media.num_attrs,
422                 sCallbackEnv->FindClass("java/lang/String"), 0));
423         if (!attrValArray.get()) {
424           log::error("can't allocate attr val array!");
425           return;
426         }
427 
428         for (int j = 0; j < item->media.num_attrs; j++) {
429           sCallbackEnv->SetIntArrayRegion(
430               attrIdArray.get(), j, 1,
431               (jint*)&(item->media.p_attrs[j].attr_id));
432           ScopedLocalRef<jstring> attrValStr(
433               sCallbackEnv.get(),
434               sCallbackEnv->NewStringUTF((char*)(item->media.p_attrs[j].text)));
435           sCallbackEnv->SetObjectArrayElement(attrValArray.get(), j,
436                                               attrValStr.get());
437         }
438 
439         ScopedLocalRef<jobject> mediaObj(
440             sCallbackEnv.get(),
441             (jobject)sCallbackEnv->CallStaticObjectMethod(
442                 class_AvrcpControllerNativeInterface,
443                 method_createFromNativeMediaItem, addr.get(), uid,
444                 (jint)item->media.type, mediaName.get(), attrIdArray.get(),
445                 attrValArray.get()));
446         if (!mediaObj.get()) {
447           log::error("failed to create AvrcpItem for type ITEM_MEDIA");
448           return;
449         }
450         sCallbackEnv->SetObjectArrayElement(itemArray.get(), i, mediaObj.get());
451         break;
452       }
453 
454       case BTRC_ITEM_FOLDER: {
455         // Parse name
456         ScopedLocalRef<jstring> folderName(
457             sCallbackEnv.get(),
458             sCallbackEnv->NewStringUTF((const char*)item->folder.name));
459         if (!folderName.get()) {
460           log::error("can't allocate folder name string!");
461           return;
462         }
463         // Parse UID
464         long long uid = *(long long*)item->folder.uid;
465         ScopedLocalRef<jobject> folderObj(
466             sCallbackEnv.get(),
467             (jobject)sCallbackEnv->CallStaticObjectMethod(
468                 class_AvrcpControllerNativeInterface,
469                 method_createFromNativeFolderItem, addr.get(), uid,
470                 (jint)item->folder.type, folderName.get(),
471                 (jint)item->folder.playable));
472         if (!folderObj.get()) {
473           log::error("failed to create AvrcpItem for type ITEM_FOLDER");
474           return;
475         }
476         sCallbackEnv->SetObjectArrayElement(itemArray.get(), i,
477                                             folderObj.get());
478         break;
479       }
480 
481       case BTRC_ITEM_PLAYER: {
482         // Parse name
483         isPlayerListing = true;
484         jint id = (jint)item->player.player_id;
485         jint playerType = (jint)item->player.major_type;
486         jint playStatus = (jint)item->player.play_status;
487         ScopedLocalRef<jbyteArray> featureBitArray(
488             sCallbackEnv.get(),
489             sCallbackEnv->NewByteArray(BTRC_FEATURE_BIT_MASK_SIZE *
490                                        sizeof(uint8_t)));
491         if (!featureBitArray.get()) {
492           log::error("failed to allocate featureBitArray");
493           return;
494         }
495         sCallbackEnv->SetByteArrayRegion(
496             featureBitArray.get(), 0,
497             sizeof(uint8_t) * BTRC_FEATURE_BIT_MASK_SIZE,
498             (jbyte*)item->player.features);
499         ScopedLocalRef<jstring> playerName(
500             sCallbackEnv.get(),
501             sCallbackEnv->NewStringUTF((const char*)item->player.name));
502         if (!playerName.get()) {
503           log::error("can't allocate player name string!");
504           return;
505         }
506         ScopedLocalRef<jobject> playerObj(
507             sCallbackEnv.get(),
508             (jobject)sCallbackEnv->CallStaticObjectMethod(
509                 class_AvrcpControllerNativeInterface,
510                 method_createFromNativePlayerItem, addr.get(), id,
511                 playerName.get(), featureBitArray.get(), playStatus,
512                 playerType));
513         if (!playerObj.get()) {
514           log::error("failed to create AvrcpPlayer from ITEM_PLAYER");
515           return;
516         }
517         sCallbackEnv->SetObjectArrayElement(itemArray.get(), i,
518                                             playerObj.get());
519         break;
520       }
521 
522       default:
523         log::error("cannot understand type {}", item->item_type);
524     }
525   }
526 
527   if (isPlayerListing) {
528     sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleGetPlayerItemsRsp,
529                                  addr.get(), itemArray.get());
530   } else {
531     sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleGetFolderItemsRsp,
532                                  addr.get(), status, itemArray.get());
533   }
534 }
535 
btavrcp_change_path_callback(const RawAddress & bd_addr,uint32_t count)536 static void btavrcp_change_path_callback(const RawAddress& bd_addr,
537                                          uint32_t count) {
538   log::info("count {}", count);
539   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
540   CallbackEnv sCallbackEnv(__func__);
541   if (!sCallbackEnv.valid()) return;
542   if (!sCallbacksObj) {
543     log::error("sCallbacksObj is null");
544     return;
545   }
546   ScopedLocalRef<jbyteArray> addr(
547       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
548   if (!addr.get()) {
549     log::error("Failed to allocate a new byte array");
550     return;
551   }
552 
553   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
554                                    (jbyte*)&bd_addr.address);
555 
556   sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleChangeFolderRsp,
557                                addr.get(), (jint)count);
558 }
559 
btavrcp_set_browsed_player_callback(const RawAddress & bd_addr,uint8_t num_items,uint8_t depth)560 static void btavrcp_set_browsed_player_callback(const RawAddress& bd_addr,
561                                                 uint8_t num_items,
562                                                 uint8_t depth) {
563   log::info("items {} depth {}", num_items, depth);
564   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
565   CallbackEnv sCallbackEnv(__func__);
566   if (!sCallbackEnv.valid()) return;
567   if (!sCallbacksObj) {
568     log::error("sCallbacksObj is null");
569     return;
570   }
571   ScopedLocalRef<jbyteArray> addr(
572       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
573   if (!addr.get()) {
574     log::error("Failed to allocate a new byte array");
575     return;
576   }
577 
578   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
579                                    (jbyte*)&bd_addr.address);
580 
581   sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleSetBrowsedPlayerRsp,
582                                addr.get(), (jint)num_items, (jint)depth);
583 }
584 
btavrcp_set_addressed_player_callback(const RawAddress & bd_addr,uint8_t status)585 static void btavrcp_set_addressed_player_callback(const RawAddress& bd_addr,
586                                                   uint8_t status) {
587   log::info("status {}", status);
588   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
589   CallbackEnv sCallbackEnv(__func__);
590   if (!sCallbackEnv.valid()) return;
591   if (!sCallbacksObj) {
592     log::error("sCallbacksObj is null");
593     return;
594   }
595   ScopedLocalRef<jbyteArray> addr(
596       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
597   if (!addr.get()) {
598     log::error("Failed to allocate a new byte array");
599     return;
600   }
601 
602   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
603                                    (jbyte*)&bd_addr.address);
604 
605   sCallbackEnv->CallVoidMethod(sCallbacksObj,
606                                method_handleSetAddressedPlayerRsp, addr.get(),
607                                (jint)status);
608 }
609 
btavrcp_addressed_player_changed_callback(const RawAddress & bd_addr,uint16_t id)610 static void btavrcp_addressed_player_changed_callback(const RawAddress& bd_addr,
611                                                       uint16_t id) {
612   log::info("status {}", id);
613   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
614   CallbackEnv sCallbackEnv(__func__);
615   if (!sCallbackEnv.valid()) return;
616   if (!sCallbacksObj) {
617     log::error("sCallbacksObj is null");
618     return;
619   }
620   ScopedLocalRef<jbyteArray> addr(
621       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
622   if (!addr.get()) {
623     log::error("Failed to allocate a new byte array");
624     return;
625   }
626 
627   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
628                                    (jbyte*)&bd_addr.address);
629 
630   sCallbackEnv->CallVoidMethod(
631       sCallbacksObj, method_handleAddressedPlayerChanged, addr.get(), (jint)id);
632 }
633 
btavrcp_now_playing_content_changed_callback(const RawAddress & bd_addr)634 static void btavrcp_now_playing_content_changed_callback(
635     const RawAddress& bd_addr) {
636   log::info("");
637 
638   CallbackEnv sCallbackEnv(__func__);
639   if (!sCallbackEnv.valid()) return;
640   ScopedLocalRef<jbyteArray> addr(
641       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
642   if (!addr.get()) {
643     log::error("Failed to allocate a new byte array");
644     return;
645   }
646 
647   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
648                                    (jbyte*)&bd_addr.address);
649 
650   sCallbackEnv->CallVoidMethod(
651       sCallbacksObj, method_handleNowPlayingContentChanged, addr.get());
652 }
653 
btavrcp_available_player_changed_callback(const RawAddress & bd_addr)654 static void btavrcp_available_player_changed_callback (
655     const RawAddress& bd_addr) {
656   log::info("");
657   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
658   CallbackEnv sCallbackEnv(__func__);
659   if (!sCallbacksObj) {
660     log::error("sCallbacksObj is null");
661     return;
662   }
663   if (!sCallbackEnv.valid()) return;
664 
665   ScopedLocalRef<jbyteArray> addr(
666       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
667   if (!addr.get()) {
668     log::error("Failed to allocate a new byte array");
669     return;
670   }
671 
672   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
673                                     (jbyte*)&bd_addr);
674   sCallbackEnv->CallVoidMethod(
675       sCallbacksObj, method_onAvailablePlayerChanged, addr.get());
676 }
677 
btavrcp_get_rcpsm_callback(const RawAddress & bd_addr,uint16_t psm)678 static void btavrcp_get_rcpsm_callback(const RawAddress& bd_addr,
679                                        uint16_t psm) {
680   log::error("-> psm received of {}", psm);
681   std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
682   CallbackEnv sCallbackEnv(__func__);
683   if (!sCallbacksObj) {
684     log::error("sCallbacksObj is null");
685     return;
686   }
687   if (!sCallbackEnv.valid()) return;
688 
689   ScopedLocalRef<jbyteArray> addr(
690       sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
691   if (!addr.get()) {
692     log::error("Failed to allocate a new byte array");
693     return;
694   }
695 
696   sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
697                                    (jbyte*)&bd_addr.address);
698   sCallbackEnv->CallVoidMethod(sCallbacksObj, method_getRcPsm, addr.get(),
699                                (jint)psm);
700 }
701 
702 static btrc_ctrl_callbacks_t sBluetoothAvrcpCallbacks = {
703     sizeof(sBluetoothAvrcpCallbacks),
704     btavrcp_passthrough_response_callback,
705     btavrcp_groupnavigation_response_callback,
706     btavrcp_connection_state_callback,
707     btavrcp_get_rcfeatures_callback,
708     btavrcp_setplayerapplicationsetting_rsp_callback,
709     btavrcp_playerapplicationsetting_callback,
710     btavrcp_playerapplicationsetting_changed_callback,
711     btavrcp_set_abs_vol_cmd_callback,
712     btavrcp_register_notification_absvol_callback,
713     btavrcp_track_changed_callback,
714     btavrcp_play_position_changed_callback,
715     btavrcp_play_status_changed_callback,
716     btavrcp_get_folder_items_callback,
717     btavrcp_change_path_callback,
718     btavrcp_set_browsed_player_callback,
719     btavrcp_set_addressed_player_callback,
720     btavrcp_addressed_player_changed_callback,
721     btavrcp_now_playing_content_changed_callback,
722     btavrcp_available_player_changed_callback,
723     btavrcp_get_rcpsm_callback,
724 };
725 
initNative(JNIEnv * env,jobject object)726 static void initNative(JNIEnv* env, jobject object) {
727   std::unique_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
728 
729   jclass tmpAvrcpItem =
730       env->FindClass("com/android/bluetooth/avrcpcontroller/AvrcpItem");
731   class_AvrcpItem = (jclass)env->NewGlobalRef(tmpAvrcpItem);
732 
733   jclass tmpBtPlayer =
734       env->FindClass("com/android/bluetooth/avrcpcontroller/AvrcpPlayer");
735   class_AvrcpPlayer = (jclass)env->NewGlobalRef(tmpBtPlayer);
736 
737   jclass tmpControllerInterface = env->FindClass(
738       "com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface");
739   class_AvrcpControllerNativeInterface =
740       (jclass)env->NewGlobalRef(tmpControllerInterface);
741 
742   const bt_interface_t* btInf = getBluetoothInterface();
743   if (btInf == NULL) {
744     log::error("Bluetooth module is not loaded");
745     return;
746   }
747 
748   if (sBluetoothAvrcpInterface != NULL) {
749     log::warn("Cleaning up Avrcp Interface before initializing...");
750     sBluetoothAvrcpInterface->cleanup();
751     sBluetoothAvrcpInterface = NULL;
752   }
753 
754   if (sCallbacksObj != NULL) {
755     log::warn("Cleaning up Avrcp callback object");
756     env->DeleteGlobalRef(sCallbacksObj);
757     sCallbacksObj = NULL;
758   }
759 
760   sBluetoothAvrcpInterface =
761       (btrc_ctrl_interface_t*)btInf->get_profile_interface(
762           BT_PROFILE_AV_RC_CTRL_ID);
763   if (sBluetoothAvrcpInterface == NULL) {
764     log::error("Failed to get Bluetooth Avrcp Controller Interface");
765     return;
766   }
767 
768   bt_status_t status =
769       sBluetoothAvrcpInterface->init(&sBluetoothAvrcpCallbacks);
770   if (status != BT_STATUS_SUCCESS) {
771     log::error("Failed to initialize Bluetooth Avrcp Controller, status: {}",
772                bt_status_text(status));
773     sBluetoothAvrcpInterface = NULL;
774     return;
775   }
776 
777   sCallbacksObj = env->NewGlobalRef(object);
778 }
779 
cleanupNative(JNIEnv * env,jobject)780 static void cleanupNative(JNIEnv* env, jobject /* object */) {
781   std::unique_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
782 
783   const bt_interface_t* btInf = getBluetoothInterface();
784   if (btInf == NULL) {
785     log::error("Bluetooth module is not loaded");
786     return;
787   }
788 
789   if (sBluetoothAvrcpInterface != NULL) {
790     sBluetoothAvrcpInterface->cleanup();
791     sBluetoothAvrcpInterface = NULL;
792   }
793 
794   if (sCallbacksObj != NULL) {
795     env->DeleteGlobalRef(sCallbacksObj);
796     sCallbacksObj = NULL;
797   }
798 }
799 
sendPassThroughCommandNative(JNIEnv * env,jobject,jbyteArray address,jint key_code,jint key_state)800 static jboolean sendPassThroughCommandNative(JNIEnv* env, jobject /* object */,
801                                              jbyteArray address, jint key_code,
802                                              jint key_state) {
803   if (!sBluetoothAvrcpInterface) return JNI_FALSE;
804 
805   log::info("sBluetoothAvrcpInterface: {}", fmt::ptr(sBluetoothAvrcpInterface));
806 
807   log::info("key_code: {}, key_state: {}", key_code, key_state);
808 
809   jbyte* addr = env->GetByteArrayElements(address, NULL);
810   if (!addr) {
811     jniThrowIOException(env, EINVAL);
812     return JNI_FALSE;
813   }
814 
815   RawAddress rawAddress;
816   rawAddress.FromOctets((uint8_t*)addr);
817   bt_status_t status = sBluetoothAvrcpInterface->send_pass_through_cmd(
818       rawAddress, (uint8_t)key_code, (uint8_t)key_state);
819   if (status != BT_STATUS_SUCCESS) {
820     log::error("Failed sending passthru command, status: {}",
821                bt_status_text(status));
822   }
823   env->ReleaseByteArrayElements(address, addr, 0);
824 
825   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
826 }
827 
sendGroupNavigationCommandNative(JNIEnv * env,jobject,jbyteArray address,jint key_code,jint key_state)828 static jboolean sendGroupNavigationCommandNative(JNIEnv* env,
829                                                  jobject /* object */,
830                                                  jbyteArray address,
831                                                  jint key_code,
832                                                  jint key_state) {
833   if (!sBluetoothAvrcpInterface) return JNI_FALSE;
834 
835   log::info("sBluetoothAvrcpInterface: {}", fmt::ptr(sBluetoothAvrcpInterface));
836 
837   log::info("key_code: {}, key_state: {}", key_code, key_state);
838 
839   jbyte* addr = env->GetByteArrayElements(address, NULL);
840   if (!addr) {
841     jniThrowIOException(env, EINVAL);
842     return JNI_FALSE;
843   }
844   RawAddress rawAddress;
845   rawAddress.FromOctets((uint8_t*)addr);
846 
847   bt_status_t status = sBluetoothAvrcpInterface->send_group_navigation_cmd(
848       rawAddress, (uint8_t)key_code, (uint8_t)key_state);
849   if (status != BT_STATUS_SUCCESS) {
850     log::error("Failed sending Grp Navigation command, status: {}",
851                bt_status_text(status));
852   }
853   env->ReleaseByteArrayElements(address, addr, 0);
854 
855   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
856 }
857 
setPlayerApplicationSettingValuesNative(JNIEnv * env,jobject,jbyteArray address,jbyte num_attrib,jbyteArray attrib_ids,jbyteArray attrib_val)858 static void setPlayerApplicationSettingValuesNative(
859     JNIEnv* env, jobject /* object */, jbyteArray address, jbyte num_attrib,
860     jbyteArray attrib_ids, jbyteArray attrib_val) {
861   log::info("sBluetoothAvrcpInterface: {}", fmt::ptr(sBluetoothAvrcpInterface));
862   if (!sBluetoothAvrcpInterface) return;
863 
864   jbyte* addr = env->GetByteArrayElements(address, NULL);
865   if (!addr) {
866     jniThrowIOException(env, EINVAL);
867     return;
868   }
869 
870   uint8_t* pAttrs = new uint8_t[num_attrib];
871   uint8_t* pAttrsVal = new uint8_t[num_attrib];
872   if ((!pAttrs) || (!pAttrsVal)) {
873     delete[] pAttrs;
874     log::error(
875         "setPlayerApplicationSettingValuesNative: not have enough memory");
876     return;
877   }
878 
879   jbyte* attr = env->GetByteArrayElements(attrib_ids, NULL);
880   jbyte* attr_val = env->GetByteArrayElements(attrib_val, NULL);
881   if ((!attr) || (!attr_val)) {
882     delete[] pAttrs;
883     delete[] pAttrsVal;
884     jniThrowIOException(env, EINVAL);
885     return;
886   }
887 
888   int i;
889   for (i = 0; i < num_attrib; ++i) {
890     pAttrs[i] = (uint8_t)attr[i];
891     pAttrsVal[i] = (uint8_t)attr_val[i];
892   }
893   RawAddress rawAddress;
894   rawAddress.FromOctets((uint8_t*)addr);
895 
896   bt_status_t status = sBluetoothAvrcpInterface->set_player_app_setting_cmd(
897       rawAddress, (uint8_t)num_attrib, pAttrs, pAttrsVal);
898   if (status != BT_STATUS_SUCCESS) {
899     log::error("Failed sending setPlAppSettValNative command, status: {}",
900                bt_status_text(status));
901   }
902   delete[] pAttrs;
903   delete[] pAttrsVal;
904   env->ReleaseByteArrayElements(attrib_ids, attr, 0);
905   env->ReleaseByteArrayElements(attrib_val, attr_val, 0);
906   env->ReleaseByteArrayElements(address, addr, 0);
907 }
908 
sendAbsVolRspNative(JNIEnv * env,jobject,jbyteArray address,jint abs_vol,jint label)909 static void sendAbsVolRspNative(JNIEnv* env, jobject /* object */,
910                                 jbyteArray address, jint abs_vol, jint label) {
911   if (!sBluetoothAvrcpInterface) return;
912 
913   jbyte* addr = env->GetByteArrayElements(address, NULL);
914   if (!addr) {
915     jniThrowIOException(env, EINVAL);
916     return;
917   }
918 
919   log::info("sBluetoothAvrcpInterface: {}", fmt::ptr(sBluetoothAvrcpInterface));
920   RawAddress rawAddress;
921   rawAddress.FromOctets((uint8_t*)addr);
922 
923   bt_status_t status = sBluetoothAvrcpInterface->set_volume_rsp(
924       rawAddress, (uint8_t)abs_vol, (uint8_t)label);
925   if (status != BT_STATUS_SUCCESS) {
926     log::error("Failed sending sendAbsVolRspNative command, status: {}",
927                bt_status_text(status));
928   }
929   env->ReleaseByteArrayElements(address, addr, 0);
930 }
931 
sendRegisterAbsVolRspNative(JNIEnv * env,jobject,jbyteArray address,jbyte rsp_type,jint abs_vol,jint label)932 static void sendRegisterAbsVolRspNative(JNIEnv* env, jobject /* object */,
933                                         jbyteArray address, jbyte rsp_type,
934                                         jint abs_vol, jint label) {
935   if (!sBluetoothAvrcpInterface) return;
936 
937   jbyte* addr = env->GetByteArrayElements(address, NULL);
938   if (!addr) {
939     jniThrowIOException(env, EINVAL);
940     return;
941   }
942   log::info("sBluetoothAvrcpInterface: {}", fmt::ptr(sBluetoothAvrcpInterface));
943   RawAddress rawAddress;
944   rawAddress.FromOctets((uint8_t*)addr);
945 
946   bt_status_t status = sBluetoothAvrcpInterface->register_abs_vol_rsp(
947       rawAddress, (btrc_notification_type_t)rsp_type, (uint8_t)abs_vol,
948       (uint8_t)label);
949   if (status != BT_STATUS_SUCCESS) {
950     log::error("Failed sending sendRegisterAbsVolRspNative command, status: {}",
951                bt_status_text(status));
952   }
953   env->ReleaseByteArrayElements(address, addr, 0);
954 }
955 
getCurrentMetadataNative(JNIEnv * env,jobject,jbyteArray address)956 static void getCurrentMetadataNative(JNIEnv* env, jobject /* object */,
957                                      jbyteArray address) {
958   if (!sBluetoothAvrcpInterface) return;
959 
960   jbyte* addr = env->GetByteArrayElements(address, NULL);
961   if (!addr) {
962     jniThrowIOException(env, EINVAL);
963     return;
964   }
965   log::verbose("sBluetoothAvrcpInterface: {}",
966                fmt::ptr(sBluetoothAvrcpInterface));
967   RawAddress rawAddress;
968   rawAddress.FromOctets((uint8_t*)addr);
969 
970   bt_status_t status =
971       sBluetoothAvrcpInterface->get_current_metadata_cmd(rawAddress);
972   if (status != BT_STATUS_SUCCESS) {
973     log::error("Failed sending getCurrentMetadataNative command, status: {}",
974                bt_status_text(status));
975   }
976   env->ReleaseByteArrayElements(address, addr, 0);
977 }
978 
getPlaybackStateNative(JNIEnv * env,jobject,jbyteArray address)979 static void getPlaybackStateNative(JNIEnv* env, jobject /* object */,
980                                    jbyteArray address) {
981   if (!sBluetoothAvrcpInterface) return;
982 
983   jbyte* addr = env->GetByteArrayElements(address, NULL);
984   if (!addr) {
985     jniThrowIOException(env, EINVAL);
986     return;
987   }
988   log::verbose("sBluetoothAvrcpInterface: {}",
989                fmt::ptr(sBluetoothAvrcpInterface));
990   RawAddress rawAddress;
991   rawAddress.FromOctets((uint8_t*)addr);
992 
993   bt_status_t status =
994       sBluetoothAvrcpInterface->get_playback_state_cmd(rawAddress);
995   if (status != BT_STATUS_SUCCESS) {
996     log::error("Failed sending getPlaybackStateNative command, status: {}",
997                bt_status_text(status));
998   }
999   env->ReleaseByteArrayElements(address, addr, 0);
1000 }
1001 
getNowPlayingListNative(JNIEnv * env,jobject,jbyteArray address,jint start,jint end)1002 static void getNowPlayingListNative(JNIEnv* env, jobject /* object */,
1003                                     jbyteArray address, jint start, jint end) {
1004   if (!sBluetoothAvrcpInterface) return;
1005   jbyte* addr = env->GetByteArrayElements(address, NULL);
1006   if (!addr) {
1007     jniThrowIOException(env, EINVAL);
1008     return;
1009   }
1010   log::verbose("sBluetoothAvrcpInterface: {}",
1011                fmt::ptr(sBluetoothAvrcpInterface));
1012   RawAddress rawAddress;
1013   rawAddress.FromOctets((uint8_t*)addr);
1014 
1015   bt_status_t status = sBluetoothAvrcpInterface->get_now_playing_list_cmd(
1016       rawAddress, start, end);
1017   if (status != BT_STATUS_SUCCESS) {
1018     log::error("Failed sending getNowPlayingListNative command, status: {}",
1019                bt_status_text(status));
1020   }
1021   env->ReleaseByteArrayElements(address, addr, 0);
1022 }
1023 
getFolderListNative(JNIEnv * env,jobject,jbyteArray address,jint start,jint end)1024 static void getFolderListNative(JNIEnv* env, jobject /* object */,
1025                                 jbyteArray address, jint start, jint end) {
1026   if (!sBluetoothAvrcpInterface) return;
1027   jbyte* addr = env->GetByteArrayElements(address, NULL);
1028   if (!addr) {
1029     jniThrowIOException(env, EINVAL);
1030     return;
1031   }
1032   log::verbose("sBluetoothAvrcpInterface: {}",
1033                fmt::ptr(sBluetoothAvrcpInterface));
1034   RawAddress rawAddress;
1035   rawAddress.FromOctets((uint8_t*)addr);
1036 
1037   bt_status_t status =
1038       sBluetoothAvrcpInterface->get_folder_list_cmd(rawAddress, start, end);
1039   if (status != BT_STATUS_SUCCESS) {
1040     log::error("Failed sending getFolderListNative command, status: {}",
1041                bt_status_text(status));
1042   }
1043   env->ReleaseByteArrayElements(address, addr, 0);
1044 }
1045 
getPlayerListNative(JNIEnv * env,jobject,jbyteArray address,jint start,jint end)1046 static void getPlayerListNative(JNIEnv* env, jobject /* object */,
1047                                 jbyteArray address, jint start, jint end) {
1048   if (!sBluetoothAvrcpInterface) return;
1049   jbyte* addr = env->GetByteArrayElements(address, NULL);
1050   if (!addr) {
1051     jniThrowIOException(env, EINVAL);
1052     return;
1053   }
1054   log::info("sBluetoothAvrcpInterface: {}", fmt::ptr(sBluetoothAvrcpInterface));
1055   RawAddress rawAddress;
1056   rawAddress.FromOctets((uint8_t*)addr);
1057 
1058   bt_status_t status =
1059       sBluetoothAvrcpInterface->get_player_list_cmd(rawAddress, start, end);
1060   if (status != BT_STATUS_SUCCESS) {
1061     log::error("Failed sending getPlayerListNative command, status: {}",
1062                bt_status_text(status));
1063   }
1064   env->ReleaseByteArrayElements(address, addr, 0);
1065 }
1066 
changeFolderPathNative(JNIEnv * env,jobject,jbyteArray address,jbyte direction,jlong uid)1067 static void changeFolderPathNative(JNIEnv* env, jobject /* object */,
1068                                    jbyteArray address, jbyte direction,
1069                                    jlong uid) {
1070   if (!sBluetoothAvrcpInterface) return;
1071   jbyte* addr = env->GetByteArrayElements(address, NULL);
1072   if (!addr) {
1073     jniThrowIOException(env, EINVAL);
1074     return;
1075   }
1076 
1077   // jbyte* uid = env->GetByteArrayElements(uidarr, NULL);
1078   // if (!uid) {
1079   //  jniThrowIOException(env, EINVAL);
1080   //  return;
1081   //}
1082 
1083   log::info("sBluetoothAvrcpInterface: {}", fmt::ptr(sBluetoothAvrcpInterface));
1084   RawAddress rawAddress;
1085   rawAddress.FromOctets((uint8_t*)addr);
1086 
1087   bt_status_t status = sBluetoothAvrcpInterface->change_folder_path_cmd(
1088       rawAddress, (uint8_t)direction, (uint8_t*)&uid);
1089   if (status != BT_STATUS_SUCCESS) {
1090     log::error("Failed sending changeFolderPathNative command, status: {}",
1091                bt_status_text(status));
1092   }
1093   // env->ReleaseByteArrayElements(address, addr, 0);
1094 }
1095 
setBrowsedPlayerNative(JNIEnv * env,jobject,jbyteArray address,jint id)1096 static void setBrowsedPlayerNative(JNIEnv* env, jobject /* object */,
1097                                    jbyteArray address, jint id) {
1098   if (!sBluetoothAvrcpInterface) return;
1099   jbyte* addr = env->GetByteArrayElements(address, NULL);
1100   if (!addr) {
1101     jniThrowIOException(env, EINVAL);
1102     return;
1103   }
1104   RawAddress rawAddress;
1105   rawAddress.FromOctets((uint8_t*)addr);
1106 
1107   log::info("sBluetoothAvrcpInterface: {}", fmt::ptr(sBluetoothAvrcpInterface));
1108   bt_status_t status = sBluetoothAvrcpInterface->set_browsed_player_cmd(
1109       rawAddress, (uint16_t)id);
1110   if (status != BT_STATUS_SUCCESS) {
1111     log::error("Failed sending setBrowsedPlayerNative command, status: {}",
1112                bt_status_text(status));
1113   }
1114   env->ReleaseByteArrayElements(address, addr, 0);
1115 }
1116 
setAddressedPlayerNative(JNIEnv * env,jobject,jbyteArray address,jint id)1117 static void setAddressedPlayerNative(JNIEnv* env, jobject /* object */,
1118                                      jbyteArray address, jint id) {
1119   if (!sBluetoothAvrcpInterface) return;
1120   jbyte* addr = env->GetByteArrayElements(address, NULL);
1121   if (!addr) {
1122     jniThrowIOException(env, EINVAL);
1123     return;
1124   }
1125   RawAddress rawAddress;
1126   rawAddress.FromOctets((uint8_t*)addr);
1127 
1128   log::info("sBluetoothAvrcpInterface: {}", fmt::ptr(sBluetoothAvrcpInterface));
1129   bt_status_t status = sBluetoothAvrcpInterface->set_addressed_player_cmd(
1130       rawAddress, (uint16_t)id);
1131   if (status != BT_STATUS_SUCCESS) {
1132     log::error("Failed sending setAddressedPlayerNative command, status: {}",
1133                bt_status_text(status));
1134   }
1135   env->ReleaseByteArrayElements(address, addr, 0);
1136 }
1137 
playItemNative(JNIEnv * env,jobject,jbyteArray address,jbyte scope,jlong uid,jint uidCounter)1138 static void playItemNative(JNIEnv* env, jobject /* object */,
1139                            jbyteArray address, jbyte scope, jlong uid,
1140                            jint uidCounter) {
1141   if (!sBluetoothAvrcpInterface) return;
1142   jbyte* addr = env->GetByteArrayElements(address, NULL);
1143   if (!addr) {
1144     jniThrowIOException(env, EINVAL);
1145     return;
1146   }
1147 
1148   //  jbyte* uid = env->GetByteArrayElements(uidArr, NULL);
1149   //  if (!uid) {
1150   //    jniThrowIOException(env, EINVAL);
1151   //    return;
1152   //  }
1153   RawAddress rawAddress;
1154   rawAddress.FromOctets((uint8_t*)addr);
1155 
1156   log::info("sBluetoothAvrcpInterface: {}", fmt::ptr(sBluetoothAvrcpInterface));
1157   bt_status_t status = sBluetoothAvrcpInterface->play_item_cmd(
1158       rawAddress, (uint8_t)scope, (uint8_t*)&uid, (uint16_t)uidCounter);
1159   if (status != BT_STATUS_SUCCESS) {
1160     log::error("Failed sending playItemNative command, status: {}",
1161                bt_status_text(status));
1162   }
1163   env->ReleaseByteArrayElements(address, addr, 0);
1164 }
1165 
register_com_android_bluetooth_avrcp_controller(JNIEnv * env)1166 int register_com_android_bluetooth_avrcp_controller(JNIEnv* env) {
1167   const JNINativeMethod methods[] = {
1168       {"initNative", "()V", (void*)initNative},
1169       {"cleanupNative", "()V", (void*)cleanupNative},
1170       {"sendPassThroughCommandNative", "([BII)Z",
1171        (void*)sendPassThroughCommandNative},
1172       {"sendGroupNavigationCommandNative", "([BII)Z",
1173        (void*)sendGroupNavigationCommandNative},
1174       {"setPlayerApplicationSettingValuesNative", "([BB[B[B)V",
1175        (void*)setPlayerApplicationSettingValuesNative},
1176       {"sendAbsVolRspNative", "([BII)V", (void*)sendAbsVolRspNative},
1177       {"sendRegisterAbsVolRspNative", "([BBII)V",
1178        (void*)sendRegisterAbsVolRspNative},
1179       {"getCurrentMetadataNative", "([B)V", (void*)getCurrentMetadataNative},
1180       {"getPlaybackStateNative", "([B)V", (void*)getPlaybackStateNative},
1181       {"getNowPlayingListNative", "([BII)V", (void*)getNowPlayingListNative},
1182       {"getFolderListNative", "([BII)V", (void*)getFolderListNative},
1183       {"getPlayerListNative", "([BII)V", (void*)getPlayerListNative},
1184       {"changeFolderPathNative", "([BBJ)V", (void*)changeFolderPathNative},
1185       {"playItemNative", "([BBJI)V", (void*)playItemNative},
1186       {"setBrowsedPlayerNative", "([BI)V", (void*)setBrowsedPlayerNative},
1187       {"setAddressedPlayerNative", "([BI)V", (void*)setAddressedPlayerNative},
1188   };
1189   const int result = REGISTER_NATIVE_METHODS(
1190       env,
1191       "com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface",
1192       methods);
1193   if (result != 0) {
1194     return result;
1195   }
1196 
1197   const JNIJavaMethod javaMethods[] = {
1198       {"onConnectionStateChanged", "(ZZ[B)V", &method_onConnectionStateChanged},
1199       {"getRcPsm", "([BI)V", &method_getRcPsm},
1200       {"handlePlayerAppSetting", "([B[BI)V", &method_handleplayerappsetting},
1201       {"onPlayerAppSettingChanged", "([B[BI)V",
1202        &method_handleplayerappsettingchanged},
1203       {"handleSetAbsVolume", "([BBB)V", &method_handleSetAbsVolume},
1204       {"handleRegisterNotificationAbsVol", "([BB)V",
1205        &method_handleRegisterNotificationAbsVol},
1206       {"onTrackChanged", "([BB[I[Ljava/lang/String;)V",
1207        &method_handletrackchanged},
1208       {"onPlayPositionChanged", "([BII)V", &method_handleplaypositionchanged},
1209       {"onPlayStatusChanged", "([BB)V", &method_handleplaystatuschanged},
1210       {"handleGetFolderItemsRsp",
1211        "([BI[Lcom/android/bluetooth/avrcpcontroller/AvrcpItem;)V",
1212        &method_handleGetFolderItemsRsp},
1213       {"handleGetPlayerItemsRsp",
1214        "([B[Lcom/android/bluetooth/avrcpcontroller/AvrcpPlayer;)V",
1215        &method_handleGetPlayerItemsRsp},
1216       {"handleChangeFolderRsp", "([BI)V", &method_handleChangeFolderRsp},
1217       {"handleSetBrowsedPlayerRsp", "([BII)V",
1218        &method_handleSetBrowsedPlayerRsp},
1219       {"handleSetAddressedPlayerRsp", "([BI)V",
1220        &method_handleSetAddressedPlayerRsp},
1221       {"handleAddressedPlayerChanged", "([BI)V",
1222        &method_handleAddressedPlayerChanged},
1223       {"handleNowPlayingContentChanged", "([B)V",
1224        &method_handleNowPlayingContentChanged},
1225       {"onAvailablePlayerChanged", "([B)V", &method_onAvailablePlayerChanged},
1226       // Fetch static method
1227       {"createFromNativeMediaItem",
1228        "([BJILjava/lang/String;[I[Ljava/lang/String;)"
1229        "Lcom/android/bluetooth/avrcpcontroller/AvrcpItem;",
1230        &method_createFromNativeMediaItem, true},
1231       {"createFromNativeFolderItem",
1232        "([BJILjava/lang/String;I)"
1233        "Lcom/android/bluetooth/avrcpcontroller/AvrcpItem;",
1234        &method_createFromNativeFolderItem, true},
1235       {"createFromNativePlayerItem",
1236        "([BILjava/lang/String;[BII)"
1237        "Lcom/android/bluetooth/avrcpcontroller/AvrcpPlayer;",
1238        &method_createFromNativePlayerItem, true},
1239   };
1240   GET_JAVA_METHODS(
1241       env,
1242       "com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface",
1243       javaMethods);
1244   return 0;
1245 }
1246 }  // namespace android
1247