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