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