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