/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "BluetoothAvrcpControllerJni"

#define LOG_NDEBUG 0

#include "com_android_bluetooth.h"
#include "hardware/bt_rc.h"
#include "utils/Log.h"

#include <string.h>
#include <shared_mutex>

namespace android {
static jmethodID method_handlePassthroughRsp;
static jmethodID method_onConnectionStateChanged;
static jmethodID method_getRcFeatures;
static jmethodID method_setplayerappsettingrsp;
static jmethodID method_handleplayerappsetting;
static jmethodID method_handleplayerappsettingchanged;
static jmethodID method_handleSetAbsVolume;
static jmethodID method_handleRegisterNotificationAbsVol;
static jmethodID method_handletrackchanged;
static jmethodID method_handleplaypositionchanged;
static jmethodID method_handleplaystatuschanged;
static jmethodID method_handleGetFolderItemsRsp;
static jmethodID method_handleGetPlayerItemsRsp;
static jmethodID method_handleGroupNavigationRsp;
static jmethodID method_createFromNativeMediaItem;
static jmethodID method_createFromNativeFolderItem;
static jmethodID method_createFromNativePlayerItem;
static jmethodID method_handleChangeFolderRsp;
static jmethodID method_handleSetBrowsedPlayerRsp;
static jmethodID method_handleSetAddressedPlayerRsp;
static jmethodID method_handleAddressedPlayerChanged;
static jmethodID method_handleNowPlayingContentChanged;
static jmethodID method_onAvailablePlayerChanged;
static jmethodID method_getRcPsm;

static jclass class_AvrcpItem;
static jclass class_AvrcpPlayer;

static const btrc_ctrl_interface_t* sBluetoothAvrcpInterface = NULL;
static jobject sCallbacksObj = NULL;
static std::shared_timed_mutex sCallbacks_mutex;

static void btavrcp_passthrough_response_callback(const RawAddress& bd_addr,
                                                  int id, int pressed) {
  ALOGI("%s: id: %d, pressed: %d", __func__, id, pressed);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }

  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);
  sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handlePassthroughRsp,
                               (jint)id, (jint)pressed, addr.get());
}

static void btavrcp_groupnavigation_response_callback(int id, int pressed) {
  ALOGV("%s", __func__);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }

  sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleGroupNavigationRsp,
                               (jint)id, (jint)pressed);
}

static void btavrcp_connection_state_callback(bool rc_connect, bool br_connect,
                                              const RawAddress& bd_addr) {
  ALOGI("%s: conn state: rc: %d br: %d", __func__, rc_connect, br_connect);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }

  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)bd_addr.address);
  sCallbackEnv->CallVoidMethod(sCallbacksObj, method_onConnectionStateChanged,
                               (jboolean)rc_connect, (jboolean)br_connect,
                               addr.get());
}

static void btavrcp_get_rcfeatures_callback(const RawAddress& bd_addr,
                                            int features) {
  ALOGV("%s", __func__);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }

  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);
  sCallbackEnv->CallVoidMethod(sCallbacksObj, method_getRcFeatures, addr.get(),
                               (jint)features);
}

static void btavrcp_setplayerapplicationsetting_rsp_callback(
    const RawAddress& bd_addr, uint8_t accepted) {
  ALOGV("%s", __func__);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }

  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);
  sCallbackEnv->CallVoidMethod(sCallbacksObj, method_setplayerappsettingrsp,
                               addr.get(), (jint)accepted);
}

static void 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) {
  ALOGI("%s", __func__);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }

  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }
  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);
  /* TODO ext attrs
   * Flattening defined attributes: <id,num_values,values[]>
   */
  jint arraylen = 0;
  for (int i = 0; i < num_attr; i++) {
    /*2 bytes for id and num */
    arraylen += 2 + app_attrs[i].num_val;
  }
  ALOGV(" arraylen %d", arraylen);

  ScopedLocalRef<jbyteArray> playerattribs(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(arraylen));
  if (!playerattribs.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  for (int i = 0, k = 0; (i < num_attr) && (k < arraylen); i++) {
    sCallbackEnv->SetByteArrayRegion(playerattribs.get(), k, 1,
                                     (jbyte*)&(app_attrs[i].attr_id));
    k++;
    sCallbackEnv->SetByteArrayRegion(playerattribs.get(), k, 1,
                                     (jbyte*)&(app_attrs[i].num_val));
    k++;
    sCallbackEnv->SetByteArrayRegion(playerattribs.get(), k,
                                     app_attrs[i].num_val,
                                     (jbyte*)(app_attrs[i].attr_val));
    k = k + app_attrs[i].num_val;
  }
  sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleplayerappsetting,
                               addr.get(), playerattribs.get(), (jint)arraylen);
}

static void btavrcp_playerapplicationsetting_changed_callback(
    const RawAddress& bd_addr, const btrc_player_settings_t& vals) {
  ALOGI("%s", __func__);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }

  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }
  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);

  int arraylen = vals.num_attr * 2;
  ScopedLocalRef<jbyteArray> playerattribs(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(arraylen));
  if (!playerattribs.get()) {
    ALOGE("Fail to new jbyteArray playerattribs ");
    return;
  }
  /*
   * Flatening format: <id,val>
   */
  for (int i = 0, k = 0; (i < vals.num_attr) && (k < arraylen); i++) {
    sCallbackEnv->SetByteArrayRegion(playerattribs.get(), k, 1,
                                     (jbyte*)&(vals.attr_ids[i]));
    k++;
    sCallbackEnv->SetByteArrayRegion(playerattribs.get(), k, 1,
                                     (jbyte*)&(vals.attr_values[i]));
    k++;
  }
  sCallbackEnv->CallVoidMethod(sCallbacksObj,
                               method_handleplayerappsettingchanged, addr.get(),
                               playerattribs.get(), (jint)arraylen);
}

static void btavrcp_set_abs_vol_cmd_callback(const RawAddress& bd_addr,
                                             uint8_t abs_vol, uint8_t label) {
  ALOGI("%s", __func__);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }

  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);
  sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleSetAbsVolume,
                               addr.get(), (jbyte)abs_vol, (jbyte)label);
}

static void btavrcp_register_notification_absvol_callback(
    const RawAddress& bd_addr, uint8_t label) {
  ALOGI("%s", __func__);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }

  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);
  sCallbackEnv->CallVoidMethod(sCallbacksObj,
                               method_handleRegisterNotificationAbsVol,
                               addr.get(), (jbyte)label);
}

static void btavrcp_track_changed_callback(const RawAddress& bd_addr,
                                           uint8_t num_attr,
                                           btrc_element_attr_val_t* p_attrs) {
  /*
   * byteArray will be formatted like this: id,len,string
   * Assuming text feild to be null terminated.
   */
  ALOGI("%s", __func__);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }

  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  ScopedLocalRef<jintArray> attribIds(sCallbackEnv.get(),
                                      sCallbackEnv->NewIntArray(num_attr));
  if (!attribIds.get()) {
    ALOGE(" failed to set new array for attribIds");
    return;
  }
  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);

  jclass strclazz = sCallbackEnv->FindClass("java/lang/String");
  ScopedLocalRef<jobjectArray> stringArray(
      sCallbackEnv.get(),
      sCallbackEnv->NewObjectArray((jint)num_attr, strclazz, 0));
  if (!stringArray.get()) {
    ALOGE(" failed to get String array");
    return;
  }

  for (jint i = 0; i < num_attr; i++) {
    ScopedLocalRef<jstring> str(
        sCallbackEnv.get(),
        sCallbackEnv->NewStringUTF((char*)(p_attrs[i].text)));
    if (!str.get()) {
      ALOGE("Unable to get str");
      return;
    }
    sCallbackEnv->SetIntArrayRegion(attribIds.get(), i, 1,
                                    (jint*)&(p_attrs[i].attr_id));
    sCallbackEnv->SetObjectArrayElement(stringArray.get(), i, str.get());
  }

  sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handletrackchanged,
                               addr.get(), (jbyte)(num_attr), attribIds.get(),
                               stringArray.get());
}

static void btavrcp_play_position_changed_callback(const RawAddress& bd_addr,
                                                   uint32_t song_len,
                                                   uint32_t song_pos) {
  ALOGI("%s", __func__);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }

  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }
  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);
  sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleplaypositionchanged,
                               addr.get(), (jint)(song_len), (jint)song_pos);
}

static void btavrcp_play_status_changed_callback(
    const RawAddress& bd_addr, btrc_play_status_t play_status) {
  ALOGI("%s", __func__);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }

  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }
  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);
  sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleplaystatuschanged,
                               addr.get(), (jbyte)play_status);
}

static void btavrcp_get_folder_items_callback(
    const RawAddress& bd_addr, btrc_status_t status,
    const btrc_folder_items_t* folder_items, uint8_t count) {
  /* Folder items are list of items that can be either BTRC_ITEM_PLAYER
   * BTRC_ITEM_MEDIA, BTRC_ITEM_FOLDER. Here we translate them to their java
   * counterparts by calling the java constructor for each of the items.
   */
  ALOGV("%s count %d", __func__, count);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }

  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);

  // Inspect if the first element is a folder/item or player listing. They are
  // always exclusive.
  bool isPlayerListing =
      count > 0 && (folder_items[0].item_type == BTRC_ITEM_PLAYER);

  // Initialize arrays for Folder OR Player listing.
  ScopedLocalRef<jobjectArray> itemArray(sCallbackEnv.get(), NULL);
  if (isPlayerListing) {
    itemArray.reset(
        sCallbackEnv->NewObjectArray((jint)count, class_AvrcpPlayer, 0));
  } else {
    itemArray.reset(sCallbackEnv->NewObjectArray(
        (jint)count, class_AvrcpItem, 0));
  }
  if (!itemArray.get()) {
    ALOGE("%s itemArray allocation failed.", __func__);
    return;
  }
  for (int i = 0; i < count; i++) {
    const btrc_folder_items_t* item = &(folder_items[i]);
    ALOGV("%s item type %d", __func__, item->item_type);
    switch (item->item_type) {
      case BTRC_ITEM_MEDIA: {
        // Parse name
        ScopedLocalRef<jstring> mediaName(
            sCallbackEnv.get(),
            sCallbackEnv->NewStringUTF((const char*)item->media.name));
        if (!mediaName.get()) {
          ALOGE("%s can't allocate media name string!", __func__);
          return;
        }
        // Parse UID
        long long uid = *(long long*)item->media.uid;
        // Parse Attrs
        ScopedLocalRef<jintArray> attrIdArray(
            sCallbackEnv.get(),
            sCallbackEnv->NewIntArray(item->media.num_attrs));
        if (!attrIdArray.get()) {
          ALOGE("%s can't allocate attr id array!", __func__);
          return;
        }
        ScopedLocalRef<jobjectArray> attrValArray(
            sCallbackEnv.get(),
            sCallbackEnv->NewObjectArray(
                item->media.num_attrs,
                sCallbackEnv->FindClass("java/lang/String"), 0));
        if (!attrValArray.get()) {
          ALOGE("%s can't allocate attr val array!", __func__);
          return;
        }

        for (int j = 0; j < item->media.num_attrs; j++) {
          sCallbackEnv->SetIntArrayRegion(
              attrIdArray.get(), j, 1,
              (jint*)&(item->media.p_attrs[j].attr_id));
          ScopedLocalRef<jstring> attrValStr(
              sCallbackEnv.get(),
              sCallbackEnv->NewStringUTF((char*)(item->media.p_attrs[j].text)));
          sCallbackEnv->SetObjectArrayElement(attrValArray.get(), j,
                                              attrValStr.get());
        }

        ScopedLocalRef<jobject> mediaObj(
            sCallbackEnv.get(),
            (jobject)sCallbackEnv->CallObjectMethod(
                sCallbacksObj, method_createFromNativeMediaItem, addr.get(),
                uid, (jint)item->media.type, mediaName.get(),
                attrIdArray.get(), attrValArray.get()));
        if (!mediaObj.get()) {
          ALOGE("%s failed to create AvrcpItem for type ITEM_MEDIA", __func__);
          return;
        }
        sCallbackEnv->SetObjectArrayElement(itemArray.get(), i, mediaObj.get());
        break;
      }

      case BTRC_ITEM_FOLDER: {
        // Parse name
        ScopedLocalRef<jstring> folderName(
            sCallbackEnv.get(),
            sCallbackEnv->NewStringUTF((const char*)item->folder.name));
        if (!folderName.get()) {
          ALOGE("%s can't allocate folder name string!", __func__);
          return;
        }
        // Parse UID
        long long uid = *(long long*)item->folder.uid;
        ScopedLocalRef<jobject> folderObj(
            sCallbackEnv.get(),
            (jobject)sCallbackEnv->CallObjectMethod(
                sCallbacksObj, method_createFromNativeFolderItem, addr.get(),
                uid, (jint)item->folder.type, folderName.get(),
                (jint)item->folder.playable));
        if (!folderObj.get()) {
          ALOGE("%s failed to create AvrcpItem for type ITEM_FOLDER", __func__);
          return;
        }
        sCallbackEnv->SetObjectArrayElement(itemArray.get(), i,
                                            folderObj.get());
        break;
      }

      case BTRC_ITEM_PLAYER: {
        // Parse name
        isPlayerListing = true;
        jint id = (jint)item->player.player_id;
        jint playerType = (jint)item->player.major_type;
        jint playStatus = (jint)item->player.play_status;
        ScopedLocalRef<jbyteArray> featureBitArray(
            sCallbackEnv.get(),
            sCallbackEnv->NewByteArray(BTRC_FEATURE_BIT_MASK_SIZE *
                                       sizeof(uint8_t)));
        if (!featureBitArray.get()) {
          ALOGE("%s failed to allocate featureBitArray", __func__);
          return;
        }
        sCallbackEnv->SetByteArrayRegion(
            featureBitArray.get(), 0,
            sizeof(uint8_t) * BTRC_FEATURE_BIT_MASK_SIZE,
            (jbyte*)item->player.features);
        ScopedLocalRef<jstring> playerName(
            sCallbackEnv.get(),
            sCallbackEnv->NewStringUTF((const char*)item->player.name));
        if (!playerName.get()) {
          ALOGE("%s can't allocate player name string!", __func__);
          return;
        }
        ScopedLocalRef<jobject> playerObj(
            sCallbackEnv.get(),
            (jobject)sCallbackEnv->CallObjectMethod(
                sCallbacksObj, method_createFromNativePlayerItem, addr.get(),
                id, playerName.get(), featureBitArray.get(), playStatus,
                playerType));
        if (!playerObj.get()) {
          ALOGE("%s failed to create AvrcpPlayer from ITEM_PLAYER", __func__);
          return;
        }
        sCallbackEnv->SetObjectArrayElement(itemArray.get(), i,
                                            playerObj.get());
        break;
      }

      default:
        ALOGE("%s cannot understand type %d", __func__, item->item_type);
    }
  }

  if (isPlayerListing) {
    sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleGetPlayerItemsRsp,
                                 addr.get(), itemArray.get());
  } else {
    sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleGetFolderItemsRsp,
                                 addr.get(), status, itemArray.get());
  }
}

static void btavrcp_change_path_callback(const RawAddress& bd_addr,
                                         uint32_t count) {
  ALOGI("%s count %d", __func__, count);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);

  sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleChangeFolderRsp,
                               addr.get(), (jint)count);
}

static void btavrcp_set_browsed_player_callback(const RawAddress& bd_addr,
                                                uint8_t num_items,
                                                uint8_t depth) {
  ALOGI("%s items %d depth %d", __func__, num_items, depth);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);

  sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleSetBrowsedPlayerRsp,
                               addr.get(), (jint)num_items, (jint)depth);
}

static void btavrcp_set_addressed_player_callback(const RawAddress& bd_addr,
                                                  uint8_t status) {
  ALOGI("%s status %d", __func__, status);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);

  sCallbackEnv->CallVoidMethod(sCallbacksObj,
                               method_handleSetAddressedPlayerRsp, addr.get(),
                               (jint)status);
}

static void btavrcp_addressed_player_changed_callback(const RawAddress& bd_addr,
                                                      uint16_t id) {
  ALOGI("%s status %d", __func__, id);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);

  sCallbackEnv->CallVoidMethod(
      sCallbacksObj, method_handleAddressedPlayerChanged, addr.get(), (jint)id);
}

static void btavrcp_now_playing_content_changed_callback(
    const RawAddress& bd_addr) {
  ALOGI("%s", __func__);

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);

  sCallbackEnv->CallVoidMethod(
      sCallbacksObj, method_handleNowPlayingContentChanged, addr.get());
}

static void btavrcp_available_player_changed_callback (
    const RawAddress& bd_addr) {
  ALOGI("%s", __func__);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbacksObj) {
      ALOGE("%s: sCallbacksObj is null", __func__);
      return;
  }
  if (!sCallbackEnv.valid()) return;

  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                    (jbyte*)&bd_addr);
  sCallbackEnv->CallVoidMethod(
      sCallbacksObj, method_onAvailablePlayerChanged, addr.get());
}

static void btavrcp_get_rcpsm_callback(const RawAddress& bd_addr,
                                       uint16_t psm) {
  ALOGE("%s -> psm received of %d", __func__, psm);
  std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbacksObj) {
    ALOGE("%s: sCallbacksObj is null", __func__);
    return;
  }
  if (!sCallbackEnv.valid()) return;

  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);
  sCallbackEnv->CallVoidMethod(sCallbacksObj, method_getRcPsm, addr.get(),
                               (jint)psm);
}

static btrc_ctrl_callbacks_t sBluetoothAvrcpCallbacks = {
    sizeof(sBluetoothAvrcpCallbacks),
    btavrcp_passthrough_response_callback,
    btavrcp_groupnavigation_response_callback,
    btavrcp_connection_state_callback,
    btavrcp_get_rcfeatures_callback,
    btavrcp_setplayerapplicationsetting_rsp_callback,
    btavrcp_playerapplicationsetting_callback,
    btavrcp_playerapplicationsetting_changed_callback,
    btavrcp_set_abs_vol_cmd_callback,
    btavrcp_register_notification_absvol_callback,
    btavrcp_track_changed_callback,
    btavrcp_play_position_changed_callback,
    btavrcp_play_status_changed_callback,
    btavrcp_get_folder_items_callback,
    btavrcp_change_path_callback,
    btavrcp_set_browsed_player_callback,
    btavrcp_set_addressed_player_callback,
    btavrcp_addressed_player_changed_callback,
    btavrcp_now_playing_content_changed_callback,
    btavrcp_available_player_changed_callback,
    btavrcp_get_rcpsm_callback};

static void classInitNative(JNIEnv* env, jclass clazz) {
  method_handlePassthroughRsp =
      env->GetMethodID(clazz, "handlePassthroughRsp", "(II[B)V");

  method_handleGroupNavigationRsp =
      env->GetMethodID(clazz, "handleGroupNavigationRsp", "(II)V");

  method_onConnectionStateChanged =
      env->GetMethodID(clazz, "onConnectionStateChanged", "(ZZ[B)V");

  method_getRcFeatures = env->GetMethodID(clazz, "getRcFeatures", "([BI)V");

  method_getRcPsm = env->GetMethodID(clazz, "getRcPsm", "([BI)V");

  method_setplayerappsettingrsp =
      env->GetMethodID(clazz, "setPlayerAppSettingRsp", "([BB)V");

  method_handleplayerappsetting =
      env->GetMethodID(clazz, "handlePlayerAppSetting", "([B[BI)V");

  method_handleplayerappsettingchanged =
      env->GetMethodID(clazz, "onPlayerAppSettingChanged", "([B[BI)V");

  method_handleSetAbsVolume =
      env->GetMethodID(clazz, "handleSetAbsVolume", "([BBB)V");

  method_handleRegisterNotificationAbsVol =
      env->GetMethodID(clazz, "handleRegisterNotificationAbsVol", "([BB)V");

  method_handletrackchanged =
      env->GetMethodID(clazz, "onTrackChanged", "([BB[I[Ljava/lang/String;)V");

  method_handleplaypositionchanged =
      env->GetMethodID(clazz, "onPlayPositionChanged", "([BII)V");

  method_handleplaystatuschanged =
      env->GetMethodID(clazz, "onPlayStatusChanged", "([BB)V");

  method_handleGetFolderItemsRsp =
      env->GetMethodID(clazz, "handleGetFolderItemsRsp",
                       "([BI[Lcom/android/bluetooth/avrcpcontroller/"
                       "AvrcpItem;)V");
  method_handleGetPlayerItemsRsp = env->GetMethodID(
      clazz, "handleGetPlayerItemsRsp",
      "([B[Lcom/android/bluetooth/avrcpcontroller/AvrcpPlayer;)V");

  method_createFromNativeMediaItem =
      env->GetMethodID(clazz, "createFromNativeMediaItem",
                       "([BJILjava/lang/String;[I[Ljava/lang/String;)Lcom/"
                       "android/bluetooth/avrcpcontroller/AvrcpItem;");
  method_createFromNativeFolderItem = env->GetMethodID(
      clazz, "createFromNativeFolderItem",
      "([BJILjava/lang/String;I)Lcom/android/bluetooth/avrcpcontroller/"
      "AvrcpItem;");
  method_createFromNativePlayerItem =
      env->GetMethodID(clazz, "createFromNativePlayerItem",
                       "([BILjava/lang/String;[BII)Lcom/android/bluetooth/"
                       "avrcpcontroller/AvrcpPlayer;");
  method_handleChangeFolderRsp =
      env->GetMethodID(clazz, "handleChangeFolderRsp", "([BI)V");
  method_handleSetBrowsedPlayerRsp =
      env->GetMethodID(clazz, "handleSetBrowsedPlayerRsp", "([BII)V");
  method_handleSetAddressedPlayerRsp =
      env->GetMethodID(clazz, "handleSetAddressedPlayerRsp", "([BI)V");
  method_handleAddressedPlayerChanged =
      env->GetMethodID(clazz, "handleAddressedPlayerChanged", "([BI)V");
  method_handleNowPlayingContentChanged =
      env->GetMethodID(clazz, "handleNowPlayingContentChanged", "([B)V");
  method_onAvailablePlayerChanged =
      env->GetMethodID(clazz, "onAvailablePlayerChanged", "([B)V");

  ALOGI("%s: succeeds", __func__);
}

static void initNative(JNIEnv* env, jobject object) {
  std::unique_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);

  jclass tmpAvrcpItem =
      env->FindClass("com/android/bluetooth/avrcpcontroller/AvrcpItem");
  class_AvrcpItem = (jclass)env->NewGlobalRef(tmpAvrcpItem);

  jclass tmpBtPlayer =
      env->FindClass("com/android/bluetooth/avrcpcontroller/AvrcpPlayer");
  class_AvrcpPlayer = (jclass)env->NewGlobalRef(tmpBtPlayer);

  const bt_interface_t* btInf = getBluetoothInterface();
  if (btInf == NULL) {
    ALOGE("Bluetooth module is not loaded");
    return;
  }

  if (sBluetoothAvrcpInterface != NULL) {
    ALOGW("Cleaning up Avrcp Interface before initializing...");
    sBluetoothAvrcpInterface->cleanup();
    sBluetoothAvrcpInterface = NULL;
  }

  if (sCallbacksObj != NULL) {
    ALOGW("Cleaning up Avrcp callback object");
    env->DeleteGlobalRef(sCallbacksObj);
    sCallbacksObj = NULL;
  }

  sBluetoothAvrcpInterface =
      (btrc_ctrl_interface_t*)btInf->get_profile_interface(
          BT_PROFILE_AV_RC_CTRL_ID);
  if (sBluetoothAvrcpInterface == NULL) {
    ALOGE("Failed to get Bluetooth Avrcp Controller Interface");
    return;
  }

  bt_status_t status =
      sBluetoothAvrcpInterface->init(&sBluetoothAvrcpCallbacks);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed to initialize Bluetooth Avrcp Controller, status: %d",
          status);
    sBluetoothAvrcpInterface = NULL;
    return;
  }

  sCallbacksObj = env->NewGlobalRef(object);
}

static void cleanupNative(JNIEnv* env, jobject object) {
  std::unique_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);

  const bt_interface_t* btInf = getBluetoothInterface();
  if (btInf == NULL) {
    ALOGE("Bluetooth module is not loaded");
    return;
  }

  if (sBluetoothAvrcpInterface != NULL) {
    sBluetoothAvrcpInterface->cleanup();
    sBluetoothAvrcpInterface = NULL;
  }

  if (sCallbacksObj != NULL) {
    env->DeleteGlobalRef(sCallbacksObj);
    sCallbacksObj = NULL;
  }
}

static jboolean sendPassThroughCommandNative(JNIEnv* env, jobject object,
                                             jbyteArray address, jint key_code,
                                             jint key_state) {
  if (!sBluetoothAvrcpInterface) return JNI_FALSE;

  ALOGI("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);

  ALOGI("key_code: %d, key_state: %d", key_code, key_state);

  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return JNI_FALSE;
  }

  RawAddress rawAddress;
  rawAddress.FromOctets((uint8_t*)addr);
  bt_status_t status = sBluetoothAvrcpInterface->send_pass_through_cmd(
      rawAddress, (uint8_t)key_code, (uint8_t)key_state);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending passthru command, status: %d", status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);

  return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}

static jboolean sendGroupNavigationCommandNative(JNIEnv* env, jobject object,
                                                 jbyteArray address,
                                                 jint key_code,
                                                 jint key_state) {
  if (!sBluetoothAvrcpInterface) return JNI_FALSE;

  ALOGI("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);

  ALOGI("key_code: %d, key_state: %d", key_code, key_state);

  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return JNI_FALSE;
  }
  RawAddress rawAddress;
  rawAddress.FromOctets((uint8_t*)addr);

  bt_status_t status = sBluetoothAvrcpInterface->send_group_navigation_cmd(
      rawAddress, (uint8_t)key_code, (uint8_t)key_state);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending Grp Navigation command, status: %d", status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);

  return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}

static void setPlayerApplicationSettingValuesNative(JNIEnv* env, jobject object,
                                                    jbyteArray address,
                                                    jbyte num_attrib,
                                                    jbyteArray attrib_ids,
                                                    jbyteArray attrib_val) {
  ALOGI("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
  if (!sBluetoothAvrcpInterface) return;

  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return;
  }

  uint8_t* pAttrs = new uint8_t[num_attrib];
  uint8_t* pAttrsVal = new uint8_t[num_attrib];
  if ((!pAttrs) || (!pAttrsVal)) {
    delete[] pAttrs;
    ALOGE("setPlayerApplicationSettingValuesNative: not have enough memeory");
    return;
  }

  jbyte* attr = env->GetByteArrayElements(attrib_ids, NULL);
  jbyte* attr_val = env->GetByteArrayElements(attrib_val, NULL);
  if ((!attr) || (!attr_val)) {
    delete[] pAttrs;
    delete[] pAttrsVal;
    jniThrowIOException(env, EINVAL);
    return;
  }

  int i;
  for (i = 0; i < num_attrib; ++i) {
    pAttrs[i] = (uint8_t)attr[i];
    pAttrsVal[i] = (uint8_t)attr_val[i];
  }
  RawAddress rawAddress;
  rawAddress.FromOctets((uint8_t*)addr);

  bt_status_t status = sBluetoothAvrcpInterface->set_player_app_setting_cmd(
      rawAddress, (uint8_t)num_attrib, pAttrs, pAttrsVal);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending setPlAppSettValNative command, status: %d", status);
  }
  delete[] pAttrs;
  delete[] pAttrsVal;
  env->ReleaseByteArrayElements(attrib_ids, attr, 0);
  env->ReleaseByteArrayElements(attrib_val, attr_val, 0);
  env->ReleaseByteArrayElements(address, addr, 0);
}

static void sendAbsVolRspNative(JNIEnv* env, jobject object, jbyteArray address,
                                jint abs_vol, jint label) {
  if (!sBluetoothAvrcpInterface) return;

  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return;
  }

  ALOGI("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
  RawAddress rawAddress;
  rawAddress.FromOctets((uint8_t*)addr);

  bt_status_t status = sBluetoothAvrcpInterface->set_volume_rsp(
      rawAddress, (uint8_t)abs_vol, (uint8_t)label);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending sendAbsVolRspNative command, status: %d", status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);
}

static void sendRegisterAbsVolRspNative(JNIEnv* env, jobject object,
                                        jbyteArray address, jbyte rsp_type,
                                        jint abs_vol, jint label) {
  if (!sBluetoothAvrcpInterface) return;

  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return;
  }
  ALOGI("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
  RawAddress rawAddress;
  rawAddress.FromOctets((uint8_t*)addr);

  bt_status_t status = sBluetoothAvrcpInterface->register_abs_vol_rsp(
      rawAddress, (btrc_notification_type_t)rsp_type, (uint8_t)abs_vol,
      (uint8_t)label);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending sendRegisterAbsVolRspNative command, status: %d",
          status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);
}

static void getCurrentMetadataNative(JNIEnv* env, jobject object,
                                     jbyteArray address) {
  if (!sBluetoothAvrcpInterface) return;

  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return;
  }
  ALOGV("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
  RawAddress rawAddress;
  rawAddress.FromOctets((uint8_t*)addr);

  bt_status_t status =
      sBluetoothAvrcpInterface->get_current_metadata_cmd(rawAddress);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending getCurrentMetadataNative command, status: %d", status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);
}

static void getPlaybackStateNative(JNIEnv* env, jobject object,
                                   jbyteArray address) {
  if (!sBluetoothAvrcpInterface) return;

  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return;
  }
  ALOGV("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
  RawAddress rawAddress;
  rawAddress.FromOctets((uint8_t*)addr);

  bt_status_t status =
      sBluetoothAvrcpInterface->get_playback_state_cmd(rawAddress);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending getPlaybackStateNative command, status: %d", status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);
}

static void getNowPlayingListNative(JNIEnv* env, jobject object,
                                    jbyteArray address, jint start, jint end) {
  if (!sBluetoothAvrcpInterface) return;
  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return;
  }
  ALOGV("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
  RawAddress rawAddress;
  rawAddress.FromOctets((uint8_t*)addr);

  bt_status_t status = sBluetoothAvrcpInterface->get_now_playing_list_cmd(
      rawAddress, start, end);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending getNowPlayingListNative command, status: %d", status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);
}

static void getFolderListNative(JNIEnv* env, jobject object, jbyteArray address,
                                jint start, jint end) {
  if (!sBluetoothAvrcpInterface) return;
  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return;
  }
  ALOGV("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
  RawAddress rawAddress;
  rawAddress.FromOctets((uint8_t*)addr);

  bt_status_t status =
      sBluetoothAvrcpInterface->get_folder_list_cmd(rawAddress, start, end);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending getFolderListNative command, status: %d", status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);
}

static void getPlayerListNative(JNIEnv* env, jobject object, jbyteArray address,
                                jint start, jint end) {
  if (!sBluetoothAvrcpInterface) return;
  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return;
  }
  ALOGI("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
  RawAddress rawAddress;
  rawAddress.FromOctets((uint8_t*)addr);

  bt_status_t status =
      sBluetoothAvrcpInterface->get_player_list_cmd(rawAddress, start, end);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending getPlayerListNative command, status: %d", status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);
}

static void changeFolderPathNative(JNIEnv* env, jobject object,
                                   jbyteArray address, jbyte direction,
                                   jlong uid) {
  if (!sBluetoothAvrcpInterface) return;
  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return;
  }

  // jbyte* uid = env->GetByteArrayElements(uidarr, NULL);
  // if (!uid) {
  //  jniThrowIOException(env, EINVAL);
  //  return;
  //}

  ALOGI("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
  RawAddress rawAddress;
  rawAddress.FromOctets((uint8_t*)addr);

  bt_status_t status = sBluetoothAvrcpInterface->change_folder_path_cmd(
      rawAddress, (uint8_t)direction, (uint8_t*)&uid);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending changeFolderPathNative command, status: %d", status);
  }
  // env->ReleaseByteArrayElements(address, addr, 0);
}

static void setBrowsedPlayerNative(JNIEnv* env, jobject object,
                                   jbyteArray address, jint id) {
  if (!sBluetoothAvrcpInterface) return;
  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return;
  }
  RawAddress rawAddress;
  rawAddress.FromOctets((uint8_t*)addr);

  ALOGI("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
  bt_status_t status = sBluetoothAvrcpInterface->set_browsed_player_cmd(
      rawAddress, (uint16_t)id);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending setBrowsedPlayerNative command, status: %d", status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);
}

static void setAddressedPlayerNative(JNIEnv* env, jobject object,
                                     jbyteArray address, jint id) {
  if (!sBluetoothAvrcpInterface) return;
  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return;
  }
  RawAddress rawAddress;
  rawAddress.FromOctets((uint8_t*)addr);

  ALOGI("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
  bt_status_t status = sBluetoothAvrcpInterface->set_addressed_player_cmd(
      rawAddress, (uint16_t)id);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending setAddressedPlayerNative command, status: %d",
          status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);
}

static void playItemNative(JNIEnv* env, jobject object, jbyteArray address,
                           jbyte scope, jlong uid, jint uidCounter) {
  if (!sBluetoothAvrcpInterface) return;
  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return;
  }

  //  jbyte* uid = env->GetByteArrayElements(uidArr, NULL);
  //  if (!uid) {
  //    jniThrowIOException(env, EINVAL);
  //    return;
  //  }
  RawAddress rawAddress;
  rawAddress.FromOctets((uint8_t*)addr);

  ALOGI("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
  bt_status_t status = sBluetoothAvrcpInterface->play_item_cmd(
      rawAddress, (uint8_t)scope, (uint8_t*)&uid, (uint16_t)uidCounter);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending playItemNative command, status: %d", status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);
}

static JNINativeMethod sMethods[] = {
    {"classInitNative", "()V", (void*)classInitNative},
    {"initNative", "()V", (void*)initNative},
    {"cleanupNative", "()V", (void*)cleanupNative},
    {"sendPassThroughCommandNative", "([BII)Z",
     (void*)sendPassThroughCommandNative},
    {"sendGroupNavigationCommandNative", "([BII)Z",
     (void*)sendGroupNavigationCommandNative},
    {"setPlayerApplicationSettingValuesNative", "([BB[B[B)V",
     (void*)setPlayerApplicationSettingValuesNative},
    {"sendAbsVolRspNative", "([BII)V", (void*)sendAbsVolRspNative},
    {"sendRegisterAbsVolRspNative", "([BBII)V",
     (void*)sendRegisterAbsVolRspNative},
    {"getCurrentMetadataNative", "([B)V", (void*)getCurrentMetadataNative},
    {"getPlaybackStateNative", "([B)V", (void*)getPlaybackStateNative},
    {"getNowPlayingListNative", "([BII)V", (void*)getNowPlayingListNative},
    {"getFolderListNative", "([BII)V", (void*)getFolderListNative},
    {"getPlayerListNative", "([BII)V", (void*)getPlayerListNative},
    {"changeFolderPathNative", "([BBJ)V", (void*)changeFolderPathNative},
    {"playItemNative", "([BBJI)V", (void*)playItemNative},
    {"setBrowsedPlayerNative", "([BI)V", (void*)setBrowsedPlayerNative},
    {"setAddressedPlayerNative", "([BI)V", (void*)setAddressedPlayerNative},
};

int register_com_android_bluetooth_avrcp_controller(JNIEnv* env) {
  return jniRegisterNativeMethods(
      env, "com/android/bluetooth/avrcpcontroller/AvrcpControllerService",
      sMethods, NELEM(sMethods));
}
}
