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