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