Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae7bfdcd authored by Joseph Pirozzo's avatar Joseph Pirozzo
Browse files

Refactor A2dpSink and AvrcpController

Update Java side code to support command and response to addressed
device.  Simplify connection logic to create a new state machine per
addressed device rather than allowing connections to transfer from one
device to another, this eliminates the possibility of having AVCRP
connected to one device and A2dp connected to another one.

Bug: 120673113
Test: runtest bluetooth
Change-Id: Ia4feba10ea8ebc22834def42b57b7abf923bee04
parent ec49615a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -231,7 +231,7 @@ static JNINativeMethod sMethods[] = {

int register_com_android_bluetooth_a2dp_sink(JNIEnv* env) {
  return jniRegisterNativeMethods(
      env, "com/android/bluetooth/a2dpsink/A2dpSinkStateMachine", sMethods,
      env, "com/android/bluetooth/a2dpsink/A2dpSinkService", sMethods,
      NELEM(sMethods));
}
}
+111 −79
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ static void btavrcp_passthrough_response_callback(const RawAddress& bd_addr,
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("Fail to new jbyteArray bd addr for passthrough response");
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

@@ -109,7 +109,7 @@ static void btavrcp_connection_state_callback(bool rc_connect, bool br_connect,
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("Fail to new jbyteArray bd addr for connection state");
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

@@ -134,7 +134,7 @@ static void btavrcp_get_rcfeatures_callback(const RawAddress& bd_addr,
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("Fail to new jbyteArray bd addr ");
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

@@ -158,7 +158,7 @@ static void btavrcp_setplayerapplicationsetting_rsp_callback(
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("Fail to new jbyteArray bd addr ");
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

@@ -184,7 +184,7 @@ static void btavrcp_playerapplicationsetting_callback(
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("Fail to new jbyteArray bd addr ");
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }
  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
@@ -202,7 +202,7 @@ static void btavrcp_playerapplicationsetting_callback(
  ScopedLocalRef<jbyteArray> playerattribs(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(arraylen));
  if (!playerattribs.get()) {
    ALOGE("Fail to new jbyteArray playerattribs ");
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

@@ -236,7 +236,7 @@ static void btavrcp_playerapplicationsetting_changed_callback(
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("Fail to get new array ");
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }
  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
@@ -279,7 +279,7 @@ static void btavrcp_set_abs_vol_cmd_callback(const RawAddress& bd_addr,
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("Fail to get new array ");
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

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

@@ -333,7 +333,7 @@ static void btavrcp_track_changed_callback(const RawAddress& bd_addr,
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("Fail to get new array ");
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }

@@ -388,7 +388,7 @@ static void btavrcp_play_position_changed_callback(const RawAddress& bd_addr,
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("Fail to get new array ");
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }
  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
@@ -411,7 +411,7 @@ static void btavrcp_play_status_changed_callback(
  ScopedLocalRef<jbyteArray> addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("Fail to get new array ");
    ALOGE("%s: Failed to allocate a new byte array", __func__);
    return;
  }
  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
@@ -436,6 +436,16 @@ static void btavrcp_get_folder_items_callback(
    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 =
@@ -468,17 +478,7 @@ static void btavrcp_get_folder_items_callback(
          return;
        }
        // Parse UID
        ScopedLocalRef<jbyteArray> uidByteArray(
            sCallbackEnv.get(),
            sCallbackEnv->NewByteArray(sizeof(uint8_t) * BTRC_UID_SIZE));
        if (!uidByteArray.get()) {
          ALOGE("%s can't allocate uid array!", __func__);
          return;
        }
        sCallbackEnv->SetByteArrayRegion(uidByteArray.get(), 0,
                                         BTRC_UID_SIZE * sizeof(uint8_t),
                                         (jbyte*)item->media.uid);

        long long uid = *(long long*)item->media.uid;
        // Parse Attrs
        ScopedLocalRef<jintArray> attrIdArray(
            sCallbackEnv.get(),
@@ -504,10 +504,6 @@ static void btavrcp_get_folder_items_callback(
          ScopedLocalRef<jstring> attrValStr(
              sCallbackEnv.get(),
              sCallbackEnv->NewStringUTF((char*)(item->media.p_attrs[j].text)));
          if (!uidByteArray.get()) {
            ALOGE("%s can't allocate uid array!", __func__);
            return;
          }
          sCallbackEnv->SetObjectArrayElement(attrValArray.get(), j,
                                              attrValStr.get());
        }
@@ -515,9 +511,9 @@ static void btavrcp_get_folder_items_callback(
        ScopedLocalRef<jobject> mediaObj(
            sCallbackEnv.get(),
            (jobject)sCallbackEnv->CallObjectMethod(
                sCallbacksObj, method_createFromNativeMediaItem,
                uidByteArray.get(), (jint)item->media.type, mediaName.get(),
                attrIdArray.get(), attrValArray.get()));
                sCallbacksObj, method_createFromNativeMediaItem, uid,
                (jint)item->media.type, mediaName.get(), attrIdArray.get(),
                attrValArray.get()));
        if (!mediaObj.get()) {
          ALOGE("%s failed to creae MediaItem for type ITEM_MEDIA", __func__);
          return;
@@ -536,22 +532,12 @@ static void btavrcp_get_folder_items_callback(
          return;
        }
        // Parse UID
        ScopedLocalRef<jbyteArray> uidByteArray(
            sCallbackEnv.get(),
            sCallbackEnv->NewByteArray(sizeof(uint8_t) * BTRC_UID_SIZE));
        if (!uidByteArray.get()) {
          ALOGE("%s can't allocate uid array!", __func__);
          return;
        }
        sCallbackEnv->SetByteArrayRegion(uidByteArray.get(), 0,
                                         BTRC_UID_SIZE * sizeof(uint8_t),
                                         (jbyte*)item->folder.uid);

        long long uid = *(long long*)item->folder.uid;
        ScopedLocalRef<jobject> folderObj(
            sCallbackEnv.get(),
            (jobject)sCallbackEnv->CallObjectMethod(
                sCallbacksObj, method_createFromNativeFolderItem,
                uidByteArray.get(), (jint)item->folder.type, folderName.get(),
                sCallbacksObj, method_createFromNativeFolderItem, uid,
                (jint)item->folder.type, folderName.get(),
                (jint)item->folder.playable));
        if (!folderObj.get()) {
          ALOGE("%s failed to create MediaItem for type ITEM_FOLDER", __func__);
@@ -609,10 +595,10 @@ static void btavrcp_get_folder_items_callback(

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

@@ -626,9 +612,18 @@ static void btavrcp_change_path_callback(const RawAddress& bd_addr,
    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,
                               (jint)count);
                               addr.get(), (jint)count);
}

static void btavrcp_set_browsed_player_callback(const RawAddress& bd_addr,
@@ -642,9 +637,18 @@ static void btavrcp_set_browsed_player_callback(const RawAddress& bd_addr,
    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,
                               (jint)num_items, (jint)depth);
                               addr.get(), (jint)num_items, (jint)depth);
}

static void btavrcp_set_addressed_player_callback(const RawAddress& bd_addr,
@@ -657,9 +661,19 @@ static void btavrcp_set_addressed_player_callback(const RawAddress& bd_addr,
    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->CallVoidMethod(
      sCallbacksObj, method_handleSetAddressedPlayerRsp, (jint)status);
  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,
@@ -672,9 +686,18 @@ static void btavrcp_addressed_player_changed_callback(const RawAddress& bd_addr,
    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->CallVoidMethod(sCallbacksObj,
                               method_handleAddressedPlayerChanged, (jint)id);
  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(
@@ -683,9 +706,18 @@ static void btavrcp_now_playing_content_changed_callback(

  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->CallVoidMethod(sCallbacksObj,
                               method_handleNowPlayingContentChanged);
  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)&bd_addr.address);

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

static btrc_ctrl_callbacks_t sBluetoothAvrcpCallbacks = {
@@ -747,32 +779,32 @@ static void classInitNative(JNIEnv* env, jclass clazz) {

  method_handleGetFolderItemsRsp =
      env->GetMethodID(clazz, "handleGetFolderItemsRsp",
                       "(I[Landroid/media/browse/MediaBrowser$MediaItem;)V");
                       "([BI[Landroid/media/browse/MediaBrowser$MediaItem;)V");
  method_handleGetPlayerItemsRsp = env->GetMethodID(
      clazz, "handleGetPlayerItemsRsp",
      "([Lcom/android/bluetooth/avrcpcontroller/AvrcpPlayer;)V");
      "([B[Lcom/android/bluetooth/avrcpcontroller/AvrcpPlayer;)V");

  method_createFromNativeMediaItem =
      env->GetMethodID(clazz, "createFromNativeMediaItem",
                       "([BILjava/lang/String;[I[Ljava/lang/String;)Landroid/"
                       "(JILjava/lang/String;[I[Ljava/lang/String;)Landroid/"
                       "media/browse/MediaBrowser$MediaItem;");
  method_createFromNativeFolderItem = env->GetMethodID(
      clazz, "createFromNativeFolderItem",
      "([BILjava/lang/String;I)Landroid/media/browse/MediaBrowser$MediaItem;");
      "(JILjava/lang/String;I)Landroid/media/browse/MediaBrowser$MediaItem;");
  method_createFromNativePlayerItem =
      env->GetMethodID(clazz, "createFromNativePlayerItem",
                       "(ILjava/lang/String;[BII)Lcom/android/bluetooth/"
                       "avrcpcontroller/AvrcpPlayer;");
  method_handleChangeFolderRsp =
      env->GetMethodID(clazz, "handleChangeFolderRsp", "(I)V");
      env->GetMethodID(clazz, "handleChangeFolderRsp", "([BI)V");
  method_handleSetBrowsedPlayerRsp =
      env->GetMethodID(clazz, "handleSetBrowsedPlayerRsp", "(II)V");
      env->GetMethodID(clazz, "handleSetBrowsedPlayerRsp", "([BII)V");
  method_handleSetAddressedPlayerRsp =
      env->GetMethodID(clazz, "handleSetAddressedPlayerRsp", "(I)V");
      env->GetMethodID(clazz, "handleSetAddressedPlayerRsp", "([BI)V");
  method_handleAddressedPlayerChanged =
      env->GetMethodID(clazz, "handleAddressedPlayerChanged", "(I)V");
      env->GetMethodID(clazz, "handleAddressedPlayerChanged", "([BI)V");
  method_handleNowPlayingContentChanged =
      env->GetMethodID(clazz, "handleNowPlayingContentChanged", "()V");
      env->GetMethodID(clazz, "handleNowPlayingContentChanged", "([B)V");

  ALOGI("%s: succeeds", __func__);
}
@@ -1081,7 +1113,7 @@ static void getPlayerListNative(JNIEnv* env, jobject object, jbyteArray address,

static void changeFolderPathNative(JNIEnv* env, jobject object,
                                   jbyteArray address, jbyte direction,
                                   jbyteArray uidarr) {
                                   jlong uid) {
  if (!sBluetoothAvrcpInterface) return;
  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
@@ -1089,22 +1121,22 @@ static void changeFolderPathNative(JNIEnv* env, jobject object,
    return;
  }

  jbyte* uid = env->GetByteArrayElements(uidarr, NULL);
  if (!uid) {
    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);
      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);
  // env->ReleaseByteArrayElements(address, addr, 0);
}

static void setBrowsedPlayerNative(JNIEnv* env, jobject object,
@@ -1149,7 +1181,7 @@ static void setAddressedPlayerNative(JNIEnv* env, jobject object,
}

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

  jbyte* uid = env->GetByteArrayElements(uidArr, NULL);
  if (!uid) {
    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);
      rawAddress, (uint8_t)scope, (uint8_t*)&uid, (uint16_t)uidCounter);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed sending playItemNative command, status: %d", status);
  }
@@ -1191,8 +1223,8 @@ static JNINativeMethod sMethods[] = {
    {"getNowPlayingListNative", "([BII)V", (void*)getNowPlayingListNative},
    {"getFolderListNative", "([BII)V", (void*)getFolderListNative},
    {"getPlayerListNative", "([BII)V", (void*)getPlayerListNative},
    {"changeFolderPathNative", "([BB[B)V", (void*)changeFolderPathNative},
    {"playItemNative", "([BB[BI)V", (void*)playItemNative},
    {"changeFolderPathNative", "([BBJ)V", (void*)changeFolderPathNative},
    {"playItemNative", "([BBJI)V", (void*)playItemNative},
    {"setBrowsedPlayerNative", "([BI)V", (void*)setBrowsedPlayerNative},
    {"setAddressedPlayerNative", "([BI)V", (void*)setAddressedPlayerNative},
};
Loading