diff options
author | Ayan Ghosh <abghosh@codeaurora.org> | 2014-07-25 17:36:24 +0530 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2014-11-04 08:25:31 -0700 |
commit | 835c9bf808f64f9d87200757f28249d0eaf6f6bc (patch) | |
tree | d1bf071d2768c9f679dee354145698ab3496ed65 /jni | |
parent | dbbf831e9d357e49d91cb0e39c344177dcf8c9ce (diff) | |
download | android_packages_apps_Bluetooth-835c9bf808f64f9d87200757f28249d0eaf6f6bc.tar.gz android_packages_apps_Bluetooth-835c9bf808f64f9d87200757f28249d0eaf6f6bc.tar.bz2 android_packages_apps_Bluetooth-835c9bf808f64f9d87200757f28249d0eaf6f6bc.zip |
AVRCP 1.5 Implementation
AVRCP 1.5 Implementation
Conflicts:
src/com/android/bluetooth/avrcp/Avrcp.java
Change-Id: Ic0358a344023fd8029e932552988cfff6b6ab750
Diffstat (limited to 'jni')
-rw-r--r-- | jni/com_android_bluetooth_avrcp.cpp | 1224 |
1 files changed, 1204 insertions, 20 deletions
diff --git a/jni/com_android_bluetooth_avrcp.cpp b/jni/com_android_bluetooth_avrcp.cpp index fb6f2fdff..4a26de087 100644 --- a/jni/com_android_bluetooth_avrcp.cpp +++ b/jni/com_android_bluetooth_avrcp.cpp @@ -28,10 +28,24 @@ namespace android { static jmethodID method_getRcFeatures; static jmethodID method_getPlayStatus; +static jmethodID method_onListPlayerAttributeRequest; static jmethodID method_getElementAttr; static jmethodID method_registerNotification; static jmethodID method_volumeChangeCallback; static jmethodID method_handlePassthroughCmd; +static jmethodID method_handlePassthroughRsp; +static jmethodID method_getFolderItems; +static jmethodID method_setAddressedPlayer; +static jmethodID method_setBrowsedPlayer; +static jmethodID method_changePath; +static jmethodID method_playItem; +static jmethodID method_getItemAttr; +static jmethodID method_onListPlayerAttributeValues; +static jmethodID method_onGetPlayerAttributeValues; +static jmethodID method_setPlayerAppSetting; +static jmethodID method_getplayerattribute_text; +static jmethodID method_getplayervalue_text; +static jmethodID method_onConnectionStateChanged; static const btrc_interface_t *sBluetoothAvrcpInterface = NULL; static jobject mCallbacksObj = NULL; @@ -65,7 +79,11 @@ static void btavrcp_remote_features_callback(bt_bdaddr_t* bd_addr, btrc_remote_f } sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getRcFeatures, addr, (jint)features); + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getRcFeatures, addr, (jint)features); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); sCallbackEnv->DeleteLocalRef(addr); } @@ -78,8 +96,151 @@ static void btavrcp_get_play_status_callback() { return; } - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getPlayStatus); + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getPlayStatus); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); +} + +static void btavrcp_get_player_seeting_value_callback(btrc_player_attr_t player_att) { + ALOGI("%s", __FUNCTION__); + if (!checkCallbackThread()) { + ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); + return; + } + + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj ,method_onListPlayerAttributeValues, + (jbyte)player_att); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); +} + +static void btavrcp_get_player_attribute_id_callback() { + ALOGI("%s", __FUNCTION__); + if (!checkCallbackThread()) { + ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); + return; + } + + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj,method_onListPlayerAttributeRequest); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); +} + +static void btavrcp_getcurrent_player_app_setting_values( uint8_t num_attr, + btrc_player_attr_t *p_attrs) { + jintArray attrs; + ALOGI("%s", __FUNCTION__); + if (!checkCallbackThread()) { + ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); + return; + } + attrs = (jintArray)sCallbackEnv->NewIntArray(num_attr); + if (!attrs) { + ALOGE("Fail to new jintArray for attrs"); + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); + return; + } + sCallbackEnv->SetIntArrayRegion(attrs, 0, num_attr, (jint *)p_attrs); + + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj,method_onGetPlayerAttributeValues, + (jbyte)num_attr,attrs); + } + else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); + sCallbackEnv->DeleteLocalRef(attrs); +} + +static void btavrcp_set_playerapp_setting_value_callback(btrc_player_settings_t *attr) +{ + jbyteArray attrs_ids; + jbyteArray attrs_value; + ALOGI("%s", __FUNCTION__); + if (!checkCallbackThread()) { + ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); + return; + } + attrs_ids = (jbyteArray)sCallbackEnv->NewByteArray(attr->num_attr); + if (!attrs_ids) { + ALOGE("Fail to new jintArray for attrs"); + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); + return; + } + sCallbackEnv->SetByteArrayRegion(attrs_ids, 0, attr->num_attr, (jbyte *)attr->attr_ids); + attrs_value = (jbyteArray)sCallbackEnv->NewByteArray(attr->num_attr); + if (!attrs_value) { + ALOGE("Fail to new jintArray for attrs"); + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); + return; + } + sCallbackEnv->SetByteArrayRegion(attrs_value, 0, attr->num_attr, (jbyte *)attr->attr_values); + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_setPlayerAppSetting, + (jbyte)attr->num_attr ,attrs_ids ,attrs_value); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } + sCallbackEnv->DeleteLocalRef(attrs_ids); + sCallbackEnv->DeleteLocalRef(attrs_value); +} + +static void btavrcp_getPlayer_app_attribute_text(uint8_t num , btrc_player_attr_t *att) +{ + jbyteArray attrs; + ALOGI("%s", __FUNCTION__); + if (!checkCallbackThread()) { + ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); + return; + } + attrs = (jbyteArray)sCallbackEnv->NewByteArray(num); + if (!attrs) { + ALOGE("Fail to new jintArray for attrs"); + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); + return; + } + sCallbackEnv->SetByteArrayRegion(attrs, 0, num, (jbyte *)att); + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getplayerattribute_text, + (jbyte) num ,attrs); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } + sCallbackEnv->DeleteLocalRef(attrs); +} + +static void btavrcp_getPlayer_app_value_text(uint8_t attr_id , uint8_t num_val , uint8_t *value) +{ + jbyteArray Attr_Value ; + ALOGI("%s", __FUNCTION__); + if (!checkCallbackThread()) { + ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); + return; + } + Attr_Value = (jbyteArray)sCallbackEnv->NewByteArray(num_val); + if (!Attr_Value) { + ALOGE("Fail to new jintArray for attrs"); + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); + return; + } + sCallbackEnv->SetByteArrayRegion(Attr_Value, 0, num_val, (jbyte *)value); + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getplayervalue_text,(jbyte) attr_id, + (jbyte) num_val , Attr_Value); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } + sCallbackEnv->DeleteLocalRef(Attr_Value); } static void btavrcp_get_element_attr_callback(uint8_t num_attr, btrc_media_attr_t *p_attrs) { @@ -98,7 +259,12 @@ static void btavrcp_get_element_attr_callback(uint8_t num_attr, btrc_media_attr_ return; } sCallbackEnv->SetIntArrayRegion(attrs, 0, num_attr, (jint *)p_attrs); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getElementAttr, (jbyte)num_attr, attrs); + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getElementAttr, (jbyte)num_attr, attrs); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); sCallbackEnv->DeleteLocalRef(attrs); } @@ -110,9 +276,12 @@ static void btavrcp_register_notification_callback(btrc_event_id_t event_id, uin ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); return; } - - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_registerNotification, + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_registerNotification, (jint)event_id, (jint)param); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); } @@ -123,12 +292,60 @@ static void btavrcp_volume_change_callback(uint8_t volume, uint8_t ctype) { ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); return; } + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_volumeChangeCallback, (jint)volume, + (jint)ctype); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_volumeChangeCallback, (jint)volume, - (jint)ctype); checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); } +static void btavrcp_get_folder_items_callback(btrc_browse_folderitem_t scope , + btrc_getfolderitem_t *param) { + jint start = param->start_item; + jint end = param->end_item; + jint size = param->size; + jint num_attr = param->attr_count; + jintArray attrs; + + if (!checkCallbackThread()) { + ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); + return; + } + + if (num_attr == 0xff) { + num_attr = 0; // 0xff signifies no attribute required in response + } else if (num_attr == 0) { + num_attr = 7; // 0x00 signifies all attributes required in response + } + + attrs = (jintArray)sCallbackEnv->NewIntArray(num_attr); + if (!attrs) { + ALOGE("Fail to new jintArray for attrs"); + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); + return; + } + sCallbackEnv->SetIntArrayRegion(attrs, 0, num_attr, (jint *)param->attrs); + + ALOGI("%s", __FUNCTION__); + ALOGI("scope: %d", scope); + ALOGI("start entry: %d", start); + ALOGI("end entry: %d", end); + ALOGI("size: %d", size); + + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getFolderItems, (jbyte)scope, + start, end, size, num_attr, attrs); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } + + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); + sCallbackEnv->DeleteLocalRef(attrs); +} + static void btavrcp_passthrough_command_callback(int id, int pressed) { ALOGI("%s", __FUNCTION__); @@ -136,26 +353,137 @@ static void btavrcp_passthrough_command_callback(int id, int pressed) { ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); return; } + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_handlePassthroughCmd, (jint)id, + (jint)pressed); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_handlePassthroughCmd, (jint)id, - (jint)pressed); checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); } +static void btavrcp_set_addressed_player_callback(uint32_t player_id) { + ALOGI("%s", __FUNCTION__); + ALOGI("player id: %d", player_id); + + if (!checkCallbackThread()) { + ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); + return; + } + + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_setAddressedPlayer, (jint)player_id); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } + + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); +} + +static void btavrcp_set_browsed_player_callback(uint32_t player_id) { + ALOGI("%s", __FUNCTION__); + ALOGI("player id: %d", player_id); + + if (!checkCallbackThread()) { + ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); + return; + } + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_setBrowsedPlayer, (jint)player_id); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); +} + +static void btavrcp_change_path_callback(uint8_t direction, uint64_t uid) { + ALOGI("%s", __FUNCTION__); + ALOGI("direction: %d, uid: %lu", direction, uid); + + if (!checkCallbackThread()) { + ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); + return; + } + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_changePath, (jbyte)direction, + (jlong)uid); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); +} + +static void btavrcp_play_item_callback(uint8_t scope, uint64_t uid) { + ALOGI("%s", __FUNCTION__); + ALOGI("scope: %d, uid: %lu", scope, uid); + + if (!checkCallbackThread()) { + ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); + return; + } + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_playItem, (jbyte)scope, (jlong)uid); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } + + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); +} + +static void btavrcp_get_item_attr_callback(uint8_t scope, uint64_t uid, + uint8_t num_attr, btrc_media_attr_t *p_attrs) { + jintArray attrs; + + if (num_attr == 0xff) { + num_attr = 0; // 0xff signifies no attribute required in response + } else if (num_attr == 0) { + num_attr = 7; // 0x00 signifies all attributes required in response + } + + ALOGI("%s", __FUNCTION__); + + if (!checkCallbackThread()) { + ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); + return; + } + attrs = (jintArray)sCallbackEnv->NewIntArray(num_attr); + if (!attrs) { + ALOGE("Fail to new jintArray for attrs"); + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); + return; + } + sCallbackEnv->SetIntArrayRegion(attrs, 0, num_attr, (jint *)p_attrs); + if (mCallbacksObj) { + sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getItemAttr, (jbyte)scope, (jlong)uid, + (jbyte)num_attr, attrs); + } else { + ALOGE("%s: mCallbacksObj is null", __FUNCTION__); + } + + checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); + sCallbackEnv->DeleteLocalRef(attrs); +} static btrc_callbacks_t sBluetoothAvrcpCallbacks = { sizeof(sBluetoothAvrcpCallbacks), btavrcp_remote_features_callback, btavrcp_get_play_status_callback, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, + btavrcp_get_player_attribute_id_callback, + btavrcp_get_player_seeting_value_callback, + btavrcp_getcurrent_player_app_setting_values, + btavrcp_getPlayer_app_attribute_text, + btavrcp_getPlayer_app_value_text, + btavrcp_set_playerapp_setting_value_callback, btavrcp_get_element_attr_callback, btavrcp_register_notification_callback, btavrcp_volume_change_callback, btavrcp_passthrough_command_callback, + btavrcp_get_folder_items_callback, + btavrcp_set_addressed_player_callback, + btavrcp_set_browsed_player_callback, + btavrcp_change_path_callback, + btavrcp_play_item_callback, + btavrcp_get_item_attr_callback }; static void classInitNative(JNIEnv* env, jclass clazz) { @@ -163,19 +491,40 @@ static void classInitNative(JNIEnv* env, jclass clazz) { env->GetMethodID(clazz, "getRcFeatures", "([BI)V"); method_getPlayStatus = env->GetMethodID(clazz, "getPlayStatus", "()V"); - + method_onListPlayerAttributeRequest = + env->GetMethodID(clazz , "onListPlayerAttributeRequest" , "()V"); + method_onListPlayerAttributeValues = + env->GetMethodID(clazz , "onListPlayerAttributeValues" , "(B)V"); method_getElementAttr = env->GetMethodID(clazz, "getElementAttr", "(B[I)V"); - + method_setPlayerAppSetting = + env->GetMethodID(clazz, "setPlayerAppSetting","(B[B[B)V"); + method_getplayerattribute_text = + env->GetMethodID(clazz, "getplayerattribute_text" , "(B[B)V"); + method_getplayervalue_text = + env->GetMethodID(clazz, "getplayervalue_text" , "(BB[B)V"); method_registerNotification = env->GetMethodID(clazz, "registerNotification", "(II)V"); - + method_onGetPlayerAttributeValues = + env->GetMethodID(clazz, "onGetPlayerAttributeValues", "(B[I)V"); method_volumeChangeCallback = env->GetMethodID(clazz, "volumeChangeCallback", "(II)V"); - method_handlePassthroughCmd = env->GetMethodID(clazz, "handlePassthroughCmd", "(II)V"); - + //setAddressedPlayer: attributes to pass: Player ID + method_setAddressedPlayer = + env->GetMethodID(clazz, "setAddressedPlayer", "(I)V"); + //getFolderItems: attributes to pass: Scope, Start, End, Attr Cnt + method_getFolderItems = + env->GetMethodID(clazz, "getFolderItems", "(BIIII[I)V"); + method_setBrowsedPlayer = + env->GetMethodID(clazz, "setBrowsedPlayer", "(I)V"); + method_changePath = + env->GetMethodID(clazz, "changePath", "(BJ)V"); + method_playItem = + env->GetMethodID(clazz, "playItem", "(BJ)V"); + method_getItemAttr = + env->GetMethodID(clazz, "getItemAttr", "(BJB[I)V"); ALOGI("%s: succeeds", __FUNCTION__); } @@ -250,6 +599,252 @@ static jboolean getPlayStatusRspNative(JNIEnv *env, jobject object, jint playSta return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; } +static jboolean getListPlayerappAttrRspNative(JNIEnv *env ,jobject object , jbyte numAttr, + jbyteArray attrIds ) { + bt_status_t status; + btrc_player_attr_t *pAttrs = NULL; + int i; + jbyte *attr; + + if (!sBluetoothAvrcpInterface) return JNI_FALSE; + if( numAttr > BTRC_MAX_APP_ATTR_SIZE) { + ALOGE("get_element_attr_rsp: number of attributes exceed maximum"); + return JNI_FALSE; + } + ALOGI("getListPlayerappAttrRspNative"); + pAttrs = new btrc_player_attr_t[numAttr]; + if (!pAttrs) { + ALOGE("getListPlayerappAttrRspNative: not have enough memeory"); + return JNI_FALSE; + } + attr = env->GetByteArrayElements(attrIds, NULL); + if( !attr) { + delete[] pAttrs; + jniThrowIOException(env, EINVAL); + return JNI_FALSE ; + } + for (i = 0; i < numAttr; ++i) { + pAttrs[i] = (btrc_player_attr_t)attr[i]; + } + if (i < numAttr) { + delete[] pAttrs; + env->ReleaseByteArrayElements(attrIds, attr, 0); + return JNI_FALSE; + } + //Call Stack Method + if ((status = sBluetoothAvrcpInterface->list_player_app_attr_rsp(numAttr, pAttrs)) != + BT_STATUS_SUCCESS) { + ALOGE("Failed getelementattrrsp, status: %d", status); + } + delete[] pAttrs; + env->ReleaseByteArrayElements(attrIds, attr, 0); + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + + +static jboolean getPlayerAppValueRspNative(JNIEnv *env ,jobject object , jbyte numvalue, + jbyteArray value) +{ + bt_status_t status; + uint8_t *pAttrs = NULL; + int i; + jbyte *attr; + + if( numvalue > BTRC_MAX_APP_ATTR_SIZE) { + ALOGE("get_element_attr_rsp: number of attributes exceed maximum"); + return JNI_FALSE; + } + pAttrs = new uint8_t[numvalue]; + if (!pAttrs) { + ALOGE("getPlayerAppValueRspNative: not have enough memeory"); + return JNI_FALSE; + } + attr = env->GetByteArrayElements(value, NULL); + if (!attr) { + delete[] pAttrs; + jniThrowIOException(env, EINVAL); + return JNI_FALSE; + } + for (i = 0; i < numvalue; ++i) { + pAttrs[i] = (uint8_t)attr[i]; + } + if (i < numvalue) { + delete[] pAttrs; + env->ReleaseByteArrayElements(value, attr, 0); + return JNI_FALSE; + } + if ((status = sBluetoothAvrcpInterface->list_player_app_value_rsp(numvalue, pAttrs)) != + BT_STATUS_SUCCESS) { + ALOGE("Failed get_element_attr_rsp, status: %d", status); + } + delete[] pAttrs; + env->ReleaseByteArrayElements(value, attr, 0); + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +static jboolean SendCurrentPlayerValueRspNative(JNIEnv *env, jobject object , + jbyte numattr ,jbyteArray value) { + btrc_player_settings_t *pAttrs = NULL ; + bt_status_t status; + int i; + jbyte *attr; + + if( numattr > BTRC_MAX_APP_ATTR_SIZE || numattr == 0) { + ALOGE("SendCurrentPlayerValueRspNative: number of attributes exceed maximum"); + return JNI_FALSE; + } + pAttrs = new btrc_player_settings_t; + if (!pAttrs) { + ALOGE("SendCurrentPlayerValueRspNative: not have enough memeory"); + return JNI_FALSE; + } + attr = env->GetByteArrayElements(value, NULL); + if (!attr) { + delete pAttrs; + jniThrowIOException(env, EINVAL); + return JNI_FALSE; + } + pAttrs->num_attr = numattr/2 ; + for(i =0 ; i < numattr; i+=2) + { + pAttrs->attr_ids[i/2] = attr[i]; + pAttrs->attr_values[i/2] = attr[i+1]; + } + if ((status = sBluetoothAvrcpInterface->get_player_app_value_rsp(pAttrs)) != + BT_STATUS_SUCCESS) { + ALOGE("Failed get_element_attr_rsp, status: %d", status); + } + delete pAttrs; + env->ReleaseByteArrayElements(value, attr, 0); + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + + +//JNI Method called to Respond to PDU 0x14 +static jboolean SendSetPlayerAppRspNative(JNIEnv *env, jobject object) +{ + bt_status_t status; + btrc_status_t player_rsp = BTRC_STS_NO_ERROR; + if ((status = sBluetoothAvrcpInterface->set_player_app_value_rsp(player_rsp)) != + BT_STATUS_SUCCESS) { + ALOGE("Failed get_element_attr_rsp, status: %d", status); + } + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + + +//JNI Method Called to Respond to PDU 0x15 +static jboolean sendSettingsTextRspNative(JNIEnv *env, jobject object, jint num_attr, + jbyteArray attr,jint length , jobjectArray textArray ) { + btrc_player_setting_text_t *pAttrs = NULL; + bt_status_t status; + int i; + jstring text; + const char* textStr; + jbyte *arr ; + + if (!sBluetoothAvrcpInterface) return JNI_FALSE; + if (num_attr > BTRC_MAX_ELEM_ATTR_SIZE) { + ALOGE("get_element_attr_rsp: number of attributes exceed maximum"); + return JNI_FALSE; + } + pAttrs = new btrc_player_setting_text_t[num_attr]; + if (!pAttrs) { + ALOGE("sendSettingsTextRspNative: not have enough memeory"); + return JNI_FALSE; + } + arr = env->GetByteArrayElements(attr, NULL); + if (!arr) { + delete[] pAttrs; + jniThrowIOException(env, EINVAL); + return JNI_FALSE; + } + for (i = 0; i < num_attr ; ++i) { + text = (jstring) env->GetObjectArrayElement(textArray, i); + textStr = env->GetStringUTFChars(text, NULL); + if (!textStr) { + ALOGE("get_element_attr_rsp: GetStringUTFChars return NULL"); + env->DeleteLocalRef(text); + break; + } + pAttrs[i].id = arr[i]; + if (strlen(textStr) >= BTRC_MAX_ATTR_STR_LEN) { + ALOGE("sendSettingsTextRspNative: string length exceed maximum"); + strncpy((char *)pAttrs[i].text, textStr, BTRC_MAX_ATTR_STR_LEN-1); + pAttrs[i].text[BTRC_MAX_ATTR_STR_LEN-1] = 0; + } else { + strcpy((char *)pAttrs[i].text, textStr); + } + //Check out if release need to be done in for loop + env->ReleaseStringUTFChars(text, textStr); + env->DeleteLocalRef(text); + } + //Call Stack Methos to Respond PDU 0x16 + if ((status = sBluetoothAvrcpInterface->get_player_app_attr_text_rsp(num_attr, pAttrs)) + != BT_STATUS_SUCCESS) { + ALOGE("Failed get_element_attr_rsp, status: %d", status); + } + delete[] pAttrs; + env->ReleaseByteArrayElements(attr, arr, 0); + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +//JNI Method Called to respond to PDU 0x16 +static jboolean sendValueTextRspNative(JNIEnv *env, jobject object, jint num_attr, + jbyteArray attr, jint length , jobjectArray textArray ) { + btrc_player_setting_text_t *pAttrs = NULL; + bt_status_t status; + int i; + jstring text ; + const char* textStr; + jbyte *arr ; + + //ALOGE("sendValueTextRspNative"); + if (!sBluetoothAvrcpInterface) return JNI_FALSE; + if (num_attr > BTRC_MAX_ELEM_ATTR_SIZE) { + ALOGE("sendValueTextRspNative: number of attributes exceed maximum"); + return JNI_FALSE; + } + pAttrs = new btrc_player_setting_text_t[num_attr]; + if (!pAttrs) { + ALOGE("sendValueTextRspNative: not have enough memeory"); + return JNI_FALSE; + } + arr = env->GetByteArrayElements(attr, NULL); + if (!arr) { + delete[] pAttrs; + jniThrowIOException(env, EINVAL); + return JNI_FALSE; + } + for (i = 0; i < num_attr ; ++i) { + text = (jstring) env->GetObjectArrayElement(textArray, i); + textStr = env->GetStringUTFChars(text, NULL); + if (!textStr) { + ALOGE("sendValueTextRspNative: GetStringUTFChars return NULL"); + env->DeleteLocalRef(text); + break; + } + pAttrs[i].id = arr[i]; + if (strlen(textStr) >= BTRC_MAX_ATTR_STR_LEN) { + ALOGE("sendValueTextRspNative: string length exceed maximum"); + strncpy((char *)pAttrs[i].text, textStr, BTRC_MAX_ATTR_STR_LEN-1); + pAttrs[i].text[BTRC_MAX_ATTR_STR_LEN-1] = 0; + } else { + strcpy((char *)pAttrs[i].text, textStr); + } + env->ReleaseStringUTFChars(text, textStr); + env->DeleteLocalRef(text); + } + //Call Stack Method to Respond to PDU 0x16 + if ((status = sBluetoothAvrcpInterface->get_player_app_value_text_rsp(num_attr, pAttrs)) + != BT_STATUS_SUCCESS) { + ALOGE("Failed get_element_attr_rsp, status: %d", status); + } + delete[] pAttrs; + env->ReleaseByteArrayElements(attr, arr, 0); + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + static jboolean getElementAttrRspNative(JNIEnv *env, jobject object, jbyte numAttr, jintArray attrIds, jobjectArray textArray) { jint *attr; @@ -316,6 +911,46 @@ static jboolean getPlayStatusRspNative(JNIEnv *env, jobject object, jint playSta return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; } +static jboolean registerNotificationPlayerAppRspNative(JNIEnv *env, jobject object ,jint type, + jbyte numattr ,jbyteArray value) { + bt_status_t status; + int i; + jbyte *attr; + btrc_register_notification_t *param= NULL; + + if( numattr > BTRC_MAX_APP_ATTR_SIZE || numattr == 0) { + ALOGE("registerNotificationPlayerAppRspNative: number of attributes exceed maximum"); + return JNI_FALSE; + } + param = new btrc_register_notification_t; + + if (!param) { + ALOGE("registerNotificationPlayerAppRspNative: not have enough memeory"); + return JNI_FALSE; + } + attr = env->GetByteArrayElements(value, NULL); + if (!attr) { + delete param; + jniThrowIOException(env, EINVAL); + return JNI_FALSE; + } + param->player_setting.num_attr = numattr/2; + for(i =0 ; i < numattr; i+=2) + { + param->player_setting.attr_ids[i/2] = attr[i]; + param->player_setting.attr_values[i/2] = attr[i+1]; + } + //Call Stack Method + if ((status = sBluetoothAvrcpInterface->register_notification_rsp(BTRC_EVT_APP_SETTINGS_CHANGED, + (btrc_notification_type_t)type,param)) != + BT_STATUS_SUCCESS) { + ALOGE("Failed get_element_attr_rsp, status: %d", status); + } + delete param; + env->ReleaseByteArrayElements(value, attr, 0); + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + static jboolean registerNotificationRspPlayStatusNative(JNIEnv *env, jobject object, jint type, jint playStatus) { bt_status_t status; @@ -395,20 +1030,569 @@ static jboolean setVolumeNative(JNIEnv *env, jobject object, jint volume) { return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; } +static jboolean registerNotificationRspAddressedPlayerChangedNative (JNIEnv *env, + jobject object, jint type, jint playerId) { + bt_status_t status; + btrc_register_notification_t param; + + ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); + ALOGI("playerId: %d", playerId); + if (!sBluetoothAvrcpInterface) return JNI_FALSE; + + param.player_id = (uint16_t)playerId; + if ((status = sBluetoothAvrcpInterface->register_notification_rsp(BTRC_EVT_ADDRESSED_PLAYER_CHANGED, + (btrc_notification_type_t)type, ¶m)) != BT_STATUS_SUCCESS) { + ALOGE("Failed registerNotificationRspAddressedPlayerChangedNative, status: %d", status); + } + + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; + +} + +static jboolean registerNotificationRspAvailablePlayersChangedNative (JNIEnv *env, + jobject object, jint type) { + bt_status_t status; + btrc_register_notification_t param; + + ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); + if (!sBluetoothAvrcpInterface) return JNI_FALSE; + if ((status = sBluetoothAvrcpInterface->register_notification_rsp(BTRC_EVT_AVAILABLE_PLAYERS_CHANGED, + (btrc_notification_type_t)type, ¶m)) != BT_STATUS_SUCCESS) { + ALOGE("Failed registerNotificationRspAvailablePlayersChangedNative, status: %d", status); + } + + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +static jboolean registerNotificationRspNowPlayingContentChangedNative(JNIEnv *env, + jobject object, jint type) { + bt_status_t status; + btrc_register_notification_t param; + + ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); + if (!sBluetoothAvrcpInterface) return JNI_FALSE; + if ((status = sBluetoothAvrcpInterface->register_notification_rsp( + BTRC_EVT_NOW_PLAYING_CONTENT_CHANGED, (btrc_notification_type_t)type, ¶m)) != + BT_STATUS_SUCCESS) { + ALOGE("Failed registerNotificationRspNowPlayingContentChangedNative, status: %d", status); + } + + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +static jboolean getFolderItemsRspNative(JNIEnv *env, jobject object, jbyte statusCode, + jint numItems, jintArray itemType, jlongArray uid, jintArray type, + jbyteArray playable, jobjectArray displayName, jbyteArray numAtt, + jobjectArray attValues, jintArray attIds) { + bt_status_t status = BT_STATUS_SUCCESS; + btrc_folder_list_entries_t param; + int32_t *itemTypeElements; + int64_t *uidElements; + int32_t *typeElements; + int8_t *playableElements; + jstring *displayNameElements; + int8_t *numAttElements; + jstring *attValuesElements; + int32_t *attIdsElements; + jint count; + jstring text; + const char* textStr; + jsize utfStringLength = 0; + int num_attr; + + ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); + if (!sBluetoothAvrcpInterface) return JNI_FALSE; + + param.status = statusCode; + param.uid_counter = 0; + param.item_count = numItems; + + if (numItems > 0) { + itemTypeElements = env->GetIntArrayElements(itemType, NULL); + if (!itemTypeElements) { + jniThrowIOException(env, EINVAL); + return JNI_FALSE; + } + + uidElements = env->GetLongArrayElements(uid, NULL); + if (!uidElements) { + jniThrowIOException(env, EINVAL); + return JNI_FALSE; + } + + typeElements = env->GetIntArrayElements(type, NULL); + if (!typeElements) { + jniThrowIOException(env, EINVAL); + return JNI_FALSE; + } + + playableElements = env->GetByteArrayElements(playable, NULL); + if (!playableElements) { + jniThrowIOException(env, EINVAL); + return JNI_FALSE; + } + + numAttElements = env->GetByteArrayElements(numAtt, NULL); + if (!numAttElements) { + jniThrowIOException(env, EINVAL); + return JNI_FALSE; + } + + attIdsElements = env->GetIntArrayElements(attIds, NULL); + if (!attIdsElements) { + jniThrowIOException(env, EINVAL); + return JNI_FALSE; + } + } + + param.p_item_list = new btrc_folder_list_item_t[numItems]; + + for (count = 0; count < numItems; count++) { + param.p_item_list[count].item_type = (uint8_t)itemTypeElements[count]; + ALOGI("getFolderItemsRspNative: item_type: %d", param.p_item_list[count].item_type); + if (itemTypeElements[count] == BTRC_TYPE_FOLDER) { + param.p_item_list[count].u.folder.uid = uidElements[count]; + ALOGI("getFolderItemsRspNative: uid: %lu", param.p_item_list[count].u.folder.uid); + param.p_item_list[count].u.folder.type = (uint8_t)typeElements[count]; + ALOGI("getFolderItemsRspNative: type: %d", param.p_item_list[count].u.folder.type); + param.p_item_list[count].u.folder.playable = playableElements[count]; + + text = (jstring) env->GetObjectArrayElement(displayName, count); + utfStringLength = env->GetStringUTFLength(text); + if (!utfStringLength) { + ALOGE("getFolderItemsRspNative: GetStringUTFLength return NULL"); + env->DeleteLocalRef(text); + break; + } + ALOGI("getFolderItemsRspNative: Disp Elem Length: %d", utfStringLength); + + textStr = env->GetStringUTFChars(text, NULL); + if (!textStr) { + ALOGE("getFolderItemsRspNative: GetStringUTFChars return NULL"); + env->DeleteLocalRef(text); + break; + } + param.p_item_list[count].u.folder.name.charset_id = BTRC_CHARSET_UTF8; + param.p_item_list[count].u.folder.name.str_len = utfStringLength; + param.p_item_list[count].u.folder.name.p_str = new uint8_t[utfStringLength]; + strlcpy((char *)param.p_item_list[count].u.folder.name.p_str, textStr, + utfStringLength); + env->ReleaseStringUTFChars(text, textStr); + env->DeleteLocalRef(text); + } else if (itemTypeElements[count] == BTRC_TYPE_MEDIA_ELEMENT) { + num_attr = 0; + param.p_item_list[count].u.media.uid = uidElements[count]; + ALOGI("getFolderItemsRspNative: uid: %l", param.p_item_list[count].u.folder.uid); + param.p_item_list[count].u.media.type = (uint8_t)typeElements[count]; + ALOGI("getFolderItemsRspNative: type: %d", param.p_item_list[count].u.folder.type); + text = (jstring) env->GetObjectArrayElement(displayName, count); + utfStringLength = env->GetStringUTFLength(text); + if (!utfStringLength) { + ALOGE("getFolderItemsRspNative: GetStringUTFLength return NULL"); + env->DeleteLocalRef(text); + break; + } + ALOGI("getFolderItemsRspNative: Disp Elem Length: %d", utfStringLength); + + textStr = env->GetStringUTFChars(text, NULL); + if (!textStr) { + ALOGE("getFolderItemsRspNative: GetStringUTFChars return NULL"); + env->DeleteLocalRef(text); + break; + } + param.p_item_list[count].u.media.name.charset_id = BTRC_CHARSET_UTF8; + param.p_item_list[count].u.media.name.str_len = utfStringLength; + param.p_item_list[count].u.media.name.p_str = new uint8_t[utfStringLength]; + strlcpy((char *)param.p_item_list[count].u.media.name.p_str, textStr, + utfStringLength); + env->ReleaseStringUTFChars(text, textStr); + env->DeleteLocalRef(text); + ALOGI("getFolderItemsRspNative: numAttr: %d", numAttElements[count]); + param.p_item_list[count].u.media.p_attr_list = + new btrc_attr_entry_t[numAttElements[count]]; + + for (int i = 0; i < numAttElements[count]; i++) { + text = (jstring) env->GetObjectArrayElement(attValues, (7 * count) + i); + utfStringLength = env->GetStringUTFLength(text); + if (!utfStringLength) { + ALOGE("getFolderItemsRspNative: GetStringUTFLength return NULL"); + env->DeleteLocalRef(text); + continue; + } + textStr = env->GetStringUTFChars(text, NULL); + if (!textStr) { + ALOGE("getFolderItemsRspNative: GetStringUTFChars return NULL"); + env->DeleteLocalRef(text); + continue; + } + param.p_item_list[count].u.media.p_attr_list[num_attr].attr_id = + attIdsElements[(7 * count) + i]; + ALOGI("getFolderItemsRspNative: Attr id: %d", + param.p_item_list[count].u.media.p_attr_list[num_attr].attr_id); + param.p_item_list[count].u.media.p_attr_list[num_attr].name.charset_id = + BTRC_CHARSET_UTF8; + param.p_item_list[count].u.media.p_attr_list[num_attr].name.str_len = + utfStringLength; + ALOGI("getFolderItemsRspNative: Attr Length: %d", + param.p_item_list[count].u.media.p_attr_list[num_attr].name.str_len); + param.p_item_list[count].u.media.p_attr_list[num_attr].name.p_str = + new uint8_t[utfStringLength]; + strlcpy((char *)param.p_item_list[count].u.media.p_attr_list[num_attr]. + name.p_str, textStr, utfStringLength); + num_attr++; + env->ReleaseStringUTFChars(text, textStr); + env->DeleteLocalRef(text); + } + param.p_item_list[count].u.media.attr_count = num_attr; + ALOGI("getFolderItemsRspNative: effective numAttr: %d", + param.p_item_list[count].u.media.attr_count); + } + } + + if ((status = sBluetoothAvrcpInterface->get_folder_items_rsp(¶m)) != BT_STATUS_SUCCESS) { + ALOGE("Failed get_folder_items_rsp, status: %u", status); + } + + env->ReleaseIntArrayElements(itemType, itemTypeElements, 0); + env->ReleaseLongArrayElements(uid, uidElements, 0); + env->ReleaseIntArrayElements(type, typeElements, 0); + env->ReleaseByteArrayElements(playable, playableElements, 0); + env->ReleaseByteArrayElements(numAtt, numAttElements, 0); + env->ReleaseIntArrayElements(attIds, attIdsElements, 0); + + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +// MediaPlayerItems are populated as byte stream from the apps +static jboolean getMediaPlayerListRspNative(JNIEnv *env, jobject object, jbyte statusCode, + jint uidCounter, jint itemCount, jbyteArray folderItems, jintArray folderItemLengths) { + bt_status_t status; + int8_t *folderElements; + int32_t *folderElementLengths; + int32_t count = 0; + int32_t countElementLength = 0; + int32_t countTotalBytes = 0; + int32_t countTemp = 0; + int32_t checkLength = 0; + btrc_folder_list_entries_t param; + + ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); + if (!sBluetoothAvrcpInterface) return JNI_FALSE; + + folderElements = env->GetByteArrayElements(folderItems, NULL); + if (!folderElements) { + jniThrowIOException(env, EINVAL); + return JNI_FALSE; + } + + folderElementLengths = env->GetIntArrayElements(folderItemLengths, NULL); + if (!folderElementLengths) { + jniThrowIOException(env, EINVAL); + return JNI_FALSE; + } + + param.status = statusCode; + param.uid_counter = uidCounter; + param.item_count = itemCount; + ALOGI("status: %d, item count: %d", param.status, param.item_count); + param.p_item_list = new btrc_folder_list_item_t[itemCount]; + ALOGI("Intermediate List entries:"); + for (; count < itemCount; count++) { + param.p_item_list[count].item_type = folderElements[countTotalBytes]; countTotalBytes++; + param.p_item_list[count].u.player.player_id = + (uint16_t)(folderElements[countTotalBytes] & 0x00ff); countTotalBytes++; + param.p_item_list[count].u.player.player_id += + (uint16_t)((folderElements[countTotalBytes] << 8) & 0xff00); countTotalBytes++; + param.p_item_list[count].u.player.major_type = + folderElements[countTotalBytes]; countTotalBytes++; + param.p_item_list[count].u.player.sub_type = + (uint32_t)(folderElements[countTotalBytes] & 0x000000ff); countTotalBytes++; + param.p_item_list[count].u.player.sub_type += + (uint32_t)((folderElements[countTotalBytes] << 8) & 0x0000ff00); countTotalBytes++; + param.p_item_list[count].u.player.sub_type += + (uint32_t)((folderElements[countTotalBytes] << 16) & 0x00ff0000); countTotalBytes++; + param.p_item_list[count].u.player.sub_type += + (uint32_t)((folderElements[countTotalBytes] << 24) & 0xff000000); countTotalBytes++; + param.p_item_list[count].u.player.play_status = + folderElements[countTotalBytes]; countTotalBytes++; + for (countTemp = 0; countTemp < 16; countTemp ++) { + param.p_item_list[count].u.player.features[countTemp] = + folderElements[countTotalBytes]; countTotalBytes++; + } + param.p_item_list[count].u.player.name.charset_id = + (uint16_t)(folderElements[countTotalBytes] & 0x00ff); countTotalBytes++; + param.p_item_list[count].u.player.name.charset_id += + (uint16_t)((folderElements[countTotalBytes] << 8) & 0xff00); countTotalBytes++; + param.p_item_list[count].u.player.name.str_len = + (uint16_t)(folderElements[countTotalBytes] & 0x00ff); countTotalBytes++; + param.p_item_list[count].u.player.name.str_len += + (uint16_t)((folderElements[countTotalBytes] << 8) & 0xff00); countTotalBytes++; + param.p_item_list[count].u.player.name.p_str = + new uint8_t[param.p_item_list[count].u.player.name.str_len]; + for (countTemp = 0; countTemp < param.p_item_list[count].u.player.name.str_len; + countTemp ++) { + param.p_item_list[count].u.player.name.p_str[countTemp] = + folderElements[countTotalBytes]; countTotalBytes++; + } + /*To check if byte feeding went well*/ + checkLength += folderElementLengths[count]; + if (checkLength != countTotalBytes) { + ALOGE("Error Populating Intermediate Folder Entry"); + ALOGE("checkLength = %u countTotalBytes = %u", checkLength, countTotalBytes); + } + ALOGI("entry: %u", count); + ALOGI("item type: %u", param.p_item_list[count].item_type); + ALOGI("player id: %u", param.p_item_list[count].u.player.player_id); + ALOGI("major type: %u", param.p_item_list[count].u.player.major_type); + ALOGI("sub type: %u", param.p_item_list[count].u.player.sub_type); + ALOGI("play status: %u", param.p_item_list[count].u.player.play_status); + ALOGI("features: "); + for (countTemp = 0; countTemp < 16; countTemp ++) + ALOGI("%u", param.p_item_list[count].u.player.features[countTemp]); + ALOGI("charset id: %u", param.p_item_list[count].u.player.name.charset_id); + ALOGI("name len: %u", param.p_item_list[count].u.player.name.str_len); + ALOGI("name: "); + for (countTemp = 0; countTemp < param.p_item_list[count].u.player.name.str_len; + countTemp ++) { + ALOGI("%u", param.p_item_list[count].u.player.name.p_str[countTemp]); + } + } + + if ((status = sBluetoothAvrcpInterface->get_folder_items_rsp(¶m)) != + BT_STATUS_SUCCESS) { + ALOGE("Failed getMediaPlayerListRspNative, status: %u", status); + } + + env->ReleaseByteArrayElements(folderItems, folderElements, 0); + env->ReleaseIntArrayElements(folderItemLengths, folderElementLengths, 0); + + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +static jboolean setAdressedPlayerRspNative(JNIEnv *env, jobject object, jbyte statusCode) { + bt_status_t status; + + ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); + if (!sBluetoothAvrcpInterface) return JNI_FALSE; + + if ((status = sBluetoothAvrcpInterface->set_addressed_player_rsp((btrc_status_t)statusCode)) != BT_STATUS_SUCCESS) { + ALOGE("Failed setAdressedPlayerRspNative, status: %d", status); + } + + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +static jboolean getItemAttrRspNative(JNIEnv *env, jobject object, jbyte numAttr, + jintArray attrIds, jobjectArray textArray) { + jint *attr; + bt_status_t status; + jstring text; + int i; + btrc_element_attr_val_t *pAttrs = NULL; + const char* textStr; + jsize utfStringLength = 0; + + if (!sBluetoothAvrcpInterface) return JNI_FALSE; + + if (numAttr > BTRC_MAX_ELEM_ATTR_SIZE) { + ALOGE("get_item_attr_rsp: number of attributes exceed maximum"); + return JNI_FALSE; + } + + pAttrs = new btrc_element_attr_val_t[numAttr]; + if (!pAttrs) { + ALOGE("get_item_attr_rsp: not have enough memeory"); + return JNI_FALSE; + } + + attr = env->GetIntArrayElements(attrIds, NULL); + if (!attr) { + delete[] pAttrs; + jniThrowIOException(env, EINVAL); + return JNI_FALSE; + } + + for (i = 0; i < numAttr; ++i) { + text = (jstring) env->GetObjectArrayElement(textArray, i); + + utfStringLength = env->GetStringUTFLength(text); + if (!utfStringLength) { + ALOGE("setBrowsedPlayerRspNative: GetStringUTFLength return NULL"); + env->DeleteLocalRef(text); + break; + } + + textStr = env->GetStringUTFChars(text, NULL); + if (!textStr) { + ALOGE("get_item_attr_rsp: GetStringUTFChars return NULL"); + env->DeleteLocalRef(text); + break; + } + + pAttrs[i].attr_id = attr[i]; + if (utfStringLength >= BTRC_MAX_ATTR_STR_LEN) { + ALOGE("get_item_attr_rsp: string length exceed maximum"); + strlcpy((char *)pAttrs[i].text, textStr, BTRC_MAX_ATTR_STR_LEN-1); + pAttrs[i].text[BTRC_MAX_ATTR_STR_LEN-1] = 0; + } else { + strlcpy((char *)pAttrs[i].text, textStr, utfStringLength); + } + env->ReleaseStringUTFChars(text, textStr); + env->DeleteLocalRef(text); + } + + if (i < numAttr) { + delete[] pAttrs; + env->ReleaseIntArrayElements(attrIds, attr, 0); + return JNI_FALSE; + } + + if ((status = sBluetoothAvrcpInterface->get_item_attr_rsp(numAttr, pAttrs)) != + BT_STATUS_SUCCESS) { + ALOGE("Failed get_item_attr_rsp, status: %d", status); + } + + delete[] pAttrs; + env->ReleaseIntArrayElements(attrIds, attr, 0); + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +static jboolean setBrowsedPlayerRspNative(JNIEnv *env, jobject object, + jbyte statusCode, jint uidCounter, + jint itemCount, jint folderDepth, + jint charId, jobjectArray folderNames) { + bt_status_t status; + int32_t count = 0; + jstring text; + const char* textStr; + jsize utfStringLength = 0; + + btrc_set_browsed_player_rsp_t param; + + ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); + if (!sBluetoothAvrcpInterface) return JNI_FALSE; + + param.status = statusCode; + param.uid_counter = uidCounter; + param.num_items = itemCount; + param.charset_id = charId; + param.folder_depth = folderDepth; + + ALOGI("statusCode: %d", statusCode); + ALOGI("uidCounter: %d", uidCounter); + ALOGI("itemCount: %d", itemCount); + ALOGI("charId: %d", charId); + ALOGI("folderDepth: %d", folderDepth); + + param.p_folders = new btrc_name_t[folderDepth]; + + for (count = 0; count < folderDepth; ++count) { + text = (jstring) env->GetObjectArrayElement(folderNames, count); + + utfStringLength = env->GetStringUTFLength(text); + if (!utfStringLength) { + ALOGE("setBrowsedPlayerRspNative: GetStringUTFLength return NULL"); + env->DeleteLocalRef(text); + break; + } + + textStr = env->GetStringUTFChars(text, NULL); + if (!textStr) { + ALOGE("setBrowsedPlayerRspNative: GetStringUTFChars return NULL"); + env->DeleteLocalRef(text); + break; + } + + param.p_folders[count].str_len = utfStringLength; + param.p_folders[count].p_str = new uint8_t[utfStringLength]; + strlcpy((char *)param.p_folders[count].p_str, textStr, utfStringLength); + env->ReleaseStringUTFChars(text, textStr); + env->DeleteLocalRef(text); + + } + + if ((status = sBluetoothAvrcpInterface->set_browsed_player_rsp(¶m)) != BT_STATUS_SUCCESS) { + ALOGE("Failed setBrowsedPlayerRspNative, status: %u", status); + } + + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +static jboolean changePathRspNative(JNIEnv *env, jobject object, jint errStatus, jlong itemCount) { + bt_status_t status; + + if (!sBluetoothAvrcpInterface) return JNI_FALSE; + + ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); + ALOGI("status: %d, itemCount: %l", errStatus, itemCount); + + if ((status = sBluetoothAvrcpInterface->change_path_rsp((uint8_t)errStatus, + (uint32_t)itemCount))!= BT_STATUS_SUCCESS) { + ALOGE("Failed sending change path response, status: %d", status); + } + + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +static jboolean playItemRspNative(JNIEnv *env, jobject object, jint errStatus) { + bt_status_t status; + + if (!sBluetoothAvrcpInterface) return JNI_FALSE; + + ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); + ALOGI("status: %d", errStatus); + + if ((status = sBluetoothAvrcpInterface->play_item_rsp((uint8_t)errStatus))!= BT_STATUS_SUCCESS) { + ALOGE("Failed sending play item response, status: %d", status); + } + + return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + + static JNINativeMethod sMethods[] = { {"classInitNative", "()V", (void *) classInitNative}, {"initNative", "()V", (void *) initNative}, {"cleanupNative", "()V", (void *) cleanupNative}, {"getPlayStatusRspNative", "(III)Z", (void *) getPlayStatusRspNative}, {"getElementAttrRspNative", "(B[I[Ljava/lang/String;)Z", (void *) getElementAttrRspNative}, + {"getListPlayerappAttrRspNative", "(B[B)Z", (void *) getListPlayerappAttrRspNative}, + {"getPlayerAppValueRspNative", "(B[B)Z", (void *) getPlayerAppValueRspNative}, {"registerNotificationRspPlayStatusNative", "(II)Z", (void *) registerNotificationRspPlayStatusNative}, + {"SendCurrentPlayerValueRspNative", "(B[B)Z", + (void *) SendCurrentPlayerValueRspNative}, + {"registerNotificationPlayerAppRspNative", "(IB[B)Z", + (void *) registerNotificationPlayerAppRspNative}, {"registerNotificationRspTrackChangeNative", "(I[B)Z", (void *) registerNotificationRspTrackChangeNative}, + {"SendSetPlayerAppRspNative", "()Z", + (void *) SendSetPlayerAppRspNative}, + {"sendSettingsTextRspNative" , "(I[BI[Ljava/lang/String;)Z", + (void *) sendSettingsTextRspNative}, + {"sendValueTextRspNative" , "(I[BI[Ljava/lang/String;)Z", + (void *) sendValueTextRspNative}, {"registerNotificationRspPlayPosNative", "(II)Z", (void *) registerNotificationRspPlayPosNative}, {"setVolumeNative", "(I)Z", (void *) setVolumeNative}, + {"setAdressedPlayerRspNative", "(B)Z", + (void *) setAdressedPlayerRspNative}, + {"getMediaPlayerListRspNative", "(BII[B[I)Z", + (void *) getMediaPlayerListRspNative}, + {"registerNotificationRspAddressedPlayerChangedNative", "(II)Z", + (void *) registerNotificationRspAddressedPlayerChangedNative}, + {"registerNotificationRspAvailablePlayersChangedNative", "(I)Z", + (void *) registerNotificationRspAvailablePlayersChangedNative}, + {"registerNotificationRspNowPlayingContentChangedNative", "(I)Z", + (void *) registerNotificationRspNowPlayingContentChangedNative}, + {"setBrowsedPlayerRspNative", "(BIIII[Ljava/lang/String;)Z", + (void *) setBrowsedPlayerRspNative}, + {"changePathRspNative", "(IJ)Z", (void *) changePathRspNative}, + {"playItemRspNative", "(I)Z", (void *) playItemRspNative}, + {"getItemAttrRspNative", "(B[I[Ljava/lang/String;)Z", (void *) getItemAttrRspNative}, + {"getFolderItemsRspNative", "(BI[I[J[I[B[Ljava/lang/String;[B[Ljava/lang/String;[I)Z", + (void *) getFolderItemsRspNative}, }; int register_com_android_bluetooth_avrcp(JNIEnv* env) |