com_android_bluetooth_avrcp.cpp revision aa1ffd5c6bd4f016c6ed452b3551e65872eaea8e
1c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu/* 2c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * Copyright (C) 2012 The Android Open Source Project 3c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * 4c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * Licensed under the Apache License, Version 2.0 (the "License"); 5c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * you may not use this file except in compliance with the License. 6c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * You may obtain a copy of the License at 7c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * 8c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * http://www.apache.org/licenses/LICENSE-2.0 9c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * 10c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * Unless required by applicable law or agreed to in writing, software 11c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * distributed under the License is distributed on an "AS IS" BASIS, 12c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * See the License for the specific language governing permissions and 14c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * limitations under the License. 15c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu */ 16c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 17c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu#define LOG_TAG "BluetoothAvrcpServiceJni" 18c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 19c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu#define LOG_NDEBUG 0 20c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 21c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu#include "com_android_bluetooth.h" 22c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu#include "hardware/bt_rc.h" 23c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu#include "utils/Log.h" 24c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu#include "android_runtime/AndroidRuntime.h" 25c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 26c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu#include <string.h> 27c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 28c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xunamespace android { 29c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jmethodID method_getPlayStatus; 30c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jmethodID method_getElementAttr; 31c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jmethodID method_registerNotification; 32c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 33c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic const btrc_interface_t *sBluetoothAvrcpInterface = NULL; 34c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jobject mCallbacksObj = NULL; 35c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic JNIEnv *sCallbackEnv = NULL; 36c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 37c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic bool checkCallbackThread() { 38c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // Always fetch the latest callbackEnv from AdapterService. 39c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // Caching this could cause this sCallbackEnv to go out-of-sync 40c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event 41c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // is received 42c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sCallbackEnv = getCallbackEnv(); 43c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 44c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu JNIEnv* env = AndroidRuntime::getJNIEnv(); 45c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (sCallbackEnv != env || sCallbackEnv == NULL) return false; 46c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return true; 47c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 48c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 49c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void btavrcp_get_play_status_callback() { 50c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGI("%s", __FUNCTION__); 51c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 52c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!checkCallbackThread()) { 53c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 54c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 55c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 56c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 57c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getPlayStatus); 58c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 59c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 60c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 61c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void btavrcp_get_element_attr_callback(uint8_t num_attr, btrc_media_attr_t *p_attrs) { 62c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jintArray attrs; 63c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 64c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGI("%s", __FUNCTION__); 65c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 66c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!checkCallbackThread()) { 67c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 68c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 69c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 70c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrs = (jintArray)sCallbackEnv->NewIntArray(num_attr); 71c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!attrs) { 72c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Fail to new jintArray for attrs"); 73c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 74c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 75c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 76c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sCallbackEnv->SetIntArrayRegion(attrs, 0, num_attr, (jint *)p_attrs); 77c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getElementAttr, (jbyte)num_attr, attrs); 78c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 79c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sCallbackEnv->DeleteLocalRef(attrs); 80c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 81c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 82c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void btavrcp_register_notification_callback(btrc_event_id_t event_id, uint32_t param) { 83c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGI("%s", __FUNCTION__); 84c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 85c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!checkCallbackThread()) { 86c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 87c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 88c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 89c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 90c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sCallbackEnv->CallVoidMethod(mCallbacksObj, method_registerNotification, 91c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu (jint)event_id, (jint)param); 92c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 93c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 94c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 95c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic btrc_callbacks_t sBluetoothAvrcpCallbacks = { 96c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sizeof(sBluetoothAvrcpCallbacks), 97c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu btavrcp_get_play_status_callback, 98c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu NULL, 99c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu NULL, 100c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu NULL, 101c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu NULL, 102c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu NULL, 103c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu NULL, 104c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu btavrcp_get_element_attr_callback, 105c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu btavrcp_register_notification_callback 106c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}; 107c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 108c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void classInitNative(JNIEnv* env, jclass clazz) { 109c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu method_getPlayStatus = 110c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->GetMethodID(clazz, "getPlayStatus", "()V"); 111c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 112c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu method_getElementAttr = 113c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->GetMethodID(clazz, "getElementAttr", "(B[I)V"); 114c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 115c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu method_registerNotification = 116c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->GetMethodID(clazz, "registerNotification", "(II)V"); 117c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 118c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGI("%s: succeeds", __FUNCTION__); 119c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 120c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 121c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void initNative(JNIEnv *env, jobject object) { 122c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu const bt_interface_t* btInf; 123c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu bt_status_t status; 124c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 125c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ( (btInf = getBluetoothInterface()) == NULL) { 126c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Bluetooth module is not loaded"); 127c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 128c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 129c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 130c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (sBluetoothAvrcpInterface !=NULL) { 131c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGW("Cleaning up Avrcp Interface before initializing..."); 132c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sBluetoothAvrcpInterface->cleanup(); 133c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sBluetoothAvrcpInterface = NULL; 134c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 135c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 136c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (mCallbacksObj != NULL) { 137c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGW("Cleaning up Avrcp callback object"); 138c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->DeleteGlobalRef(mCallbacksObj); 139c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mCallbacksObj = NULL; 140c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 141c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 142c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ( (sBluetoothAvrcpInterface = (btrc_interface_t *) 143c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu btInf->get_profile_interface(BT_PROFILE_AV_RC_ID)) == NULL) { 144c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Failed to get Bluetooth Avrcp Interface"); 145c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 146c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 147c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 148c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ( (status = sBluetoothAvrcpInterface->init(&sBluetoothAvrcpCallbacks)) != 149c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu BT_STATUS_SUCCESS) { 150c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Failed to initialize Bluetooth Avrcp, status: %d", status); 151c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sBluetoothAvrcpInterface = NULL; 152c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 153c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 154c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 155c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mCallbacksObj = env->NewGlobalRef(object); 156c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 157c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 158c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void cleanupNative(JNIEnv *env, jobject object) { 159c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu const bt_interface_t* btInf; 160c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 161c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ( (btInf = getBluetoothInterface()) == NULL) { 162c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Bluetooth module is not loaded"); 163c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 164c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 165c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 166c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (sBluetoothAvrcpInterface !=NULL) { 167c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sBluetoothAvrcpInterface->cleanup(); 168c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sBluetoothAvrcpInterface = NULL; 169c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 170c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 171c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (mCallbacksObj != NULL) { 172c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->DeleteGlobalRef(mCallbacksObj); 173c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mCallbacksObj = NULL; 174c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 175c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 176c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 177c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jboolean getPlayStatusRspNative(JNIEnv *env, jobject object, jint playStatus, 178c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jint songLen, jint songPos) { 179c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu bt_status_t status; 180c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 181c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); 182c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!sBluetoothAvrcpInterface) return JNI_FALSE; 183c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 184c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ((status = sBluetoothAvrcpInterface->get_play_status_rsp((btrc_play_status_t)playStatus, 185c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu songLen, songPos)) != BT_STATUS_SUCCESS) { 186c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Failed get_play_status_rsp, status: %d", status); 187c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 188c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 189c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 190c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 191c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 192c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu static jboolean getElementAttrRspNative(JNIEnv *env, jobject object, jbyte numAttr, 193c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jintArray attrIds, jobjectArray textArray) { 194c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jint *attr; 195c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu bt_status_t status; 196c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jstring text; 197c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int i; 198c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu btrc_element_attr_val_t *pAttrs = NULL; 199c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu const char* textStr; 200c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 201c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!sBluetoothAvrcpInterface) return JNI_FALSE; 202c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 203c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (numAttr > BTRC_MAX_ELEM_ATTR_SIZE) { 204c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("get_element_attr_rsp: number of attributes exceed maximum"); 205c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return JNI_FALSE; 206c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 207c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 208c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu pAttrs = new btrc_element_attr_val_t[numAttr]; 209c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!pAttrs) { 210c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("get_element_attr_rsp: not have enough memeory"); 211c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return JNI_FALSE; 212c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 213c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 214c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attr = env->GetIntArrayElements(attrIds, NULL); 215c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!attr) { 216c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu delete[] pAttrs; 217c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jniThrowIOException(env, EINVAL); 218c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return JNI_FALSE; 219c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 220c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 221c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu for (i = 0; i < numAttr; ++i) { 222c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu text = (jstring) env->GetObjectArrayElement(textArray, i); 223c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu textStr = env->GetStringUTFChars(text, NULL); 224c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!textStr) { 225c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("get_element_attr_rsp: GetStringUTFChars return NULL"); 226c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->DeleteLocalRef(text); 227c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 228c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 229885213461ae72d6db178c95fafc01cde153230dbZhihai Xu 230885213461ae72d6db178c95fafc01cde153230dbZhihai Xu pAttrs[i].attr_id = attr[i]; 231c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (strlen(textStr) >= BTRC_MAX_ATTR_STR_LEN) { 232c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("get_element_attr_rsp: string length exceed maximum"); 233885213461ae72d6db178c95fafc01cde153230dbZhihai Xu strncpy((char *)pAttrs[i].text, textStr, BTRC_MAX_ATTR_STR_LEN-1); 234885213461ae72d6db178c95fafc01cde153230dbZhihai Xu pAttrs[i].text[BTRC_MAX_ATTR_STR_LEN-1] = 0; 235885213461ae72d6db178c95fafc01cde153230dbZhihai Xu } else { 236885213461ae72d6db178c95fafc01cde153230dbZhihai Xu strcpy((char *)pAttrs[i].text, textStr); 237c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 238c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->ReleaseStringUTFChars(text, textStr); 239c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->DeleteLocalRef(text); 240c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 241c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 242c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (i < numAttr) { 243c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu delete[] pAttrs; 244c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->ReleaseIntArrayElements(attrIds, attr, 0); 245c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return JNI_FALSE; 246c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 247c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 248c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ((status = sBluetoothAvrcpInterface->get_element_attr_rsp(numAttr, pAttrs)) != 249c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu BT_STATUS_SUCCESS) { 250c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Failed get_element_attr_rsp, status: %d", status); 251c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 252c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 253c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu delete[] pAttrs; 254c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->ReleaseIntArrayElements(attrIds, attr, 0); 255c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 256c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 257c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 258c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jboolean registerNotificationRspPlayStatusNative(JNIEnv *env, jobject object, 259c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jint type, jint playStatus) { 260c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu bt_status_t status; 261c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu btrc_register_notification_t param; 262c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 263c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); 264c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!sBluetoothAvrcpInterface) return JNI_FALSE; 265c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 266c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu param.play_status = (btrc_play_status_t)playStatus; 267c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ((status = sBluetoothAvrcpInterface->register_notification_rsp(BTRC_EVT_PLAY_STATUS_CHANGED, 268c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu (btrc_notification_type_t)type, ¶m)) != BT_STATUS_SUCCESS) { 269c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Failed register_notification_rsp play status, status: %d", status); 270c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 271c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 272c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 273c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 274c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 275c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jboolean registerNotificationRspTrackChangeNative(JNIEnv *env, jobject object, 276c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jint type, jbyteArray track) { 277c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu bt_status_t status; 278c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu btrc_register_notification_t param; 279c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jbyte *trk; 280c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int i; 281c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 282c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); 283c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!sBluetoothAvrcpInterface) return JNI_FALSE; 284c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 285c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu trk = env->GetByteArrayElements(track, NULL); 286c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!trk) { 287c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jniThrowIOException(env, EINVAL); 288c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return JNI_FALSE; 289c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 290c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 291c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu for (i = 0; i < BTRC_UID_SIZE; ++i) { 292c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu param.track[i] = trk[i]; 293c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 294c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 295c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ((status = sBluetoothAvrcpInterface->register_notification_rsp(BTRC_EVT_TRACK_CHANGE, 296c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu (btrc_notification_type_t)type, ¶m)) != BT_STATUS_SUCCESS) { 297c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Failed register_notification_rsp track change, status: %d", status); 298c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 299c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 300c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->ReleaseByteArrayElements(track, trk, 0); 301c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 302c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 303c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 304aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xustatic jboolean registerNotificationRspPlayPosNative(JNIEnv *env, jobject object, 305aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu jint type, jint playPos) { 306aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu bt_status_t status; 307aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu btrc_register_notification_t param; 308aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 309aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); 310aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if (!sBluetoothAvrcpInterface) return JNI_FALSE; 311aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 312aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu param.song_pos = (uint32_t)playPos; 313aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if ((status = sBluetoothAvrcpInterface->register_notification_rsp(BTRC_EVT_PLAY_POS_CHANGED, 314aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu (btrc_notification_type_t)type, ¶m)) != BT_STATUS_SUCCESS) { 315aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu ALOGE("Failed register_notification_rsp play position, status: %d", status); 316aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 317aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 318aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 319aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu} 320aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 321c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic JNINativeMethod sMethods[] = { 322c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu {"classInitNative", "()V", (void *) classInitNative}, 323c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu {"initNative", "()V", (void *) initNative}, 324c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu {"cleanupNative", "()V", (void *) cleanupNative}, 325c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu {"getPlayStatusRspNative", "(III)Z", (void *) getPlayStatusRspNative}, 326c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu {"getElementAttrRspNative", "(B[I[Ljava/lang/String;)Z", (void *) getElementAttrRspNative}, 327c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu {"registerNotificationRspPlayStatusNative", "(II)Z", 328c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu (void *) registerNotificationRspPlayStatusNative}, 329c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu {"registerNotificationRspTrackChangeNative", "(I[B)Z", 330c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu (void *) registerNotificationRspTrackChangeNative}, 331aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu {"registerNotificationRspPlayPosNative", "(II)Z", 332aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu (void *) registerNotificationRspPlayPosNative}, 333c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}; 334c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 335c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuint register_com_android_bluetooth_avrcp(JNIEnv* env) 336c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu{ 337c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return jniRegisterNativeMethods(env, "com/android/bluetooth/a2dp/Avrcp", 338c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sMethods, NELEM(sMethods)); 339c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 340c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 341c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 342