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