com_android_bluetooth_avrcp.cpp revision ace834feb02adabd61f628c4471147aea02d939c
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; 32ace834feb02adabd61f628c4471147aea02d939cJohn Dustatic jmethodID method_handlePassthroughCmd; 33c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 34c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic const btrc_interface_t *sBluetoothAvrcpInterface = NULL; 35c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jobject mCallbacksObj = NULL; 36c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic JNIEnv *sCallbackEnv = NULL; 37c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 38c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic bool checkCallbackThread() { 39c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // Always fetch the latest callbackEnv from AdapterService. 40c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // Caching this could cause this sCallbackEnv to go out-of-sync 41c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event 42c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // is received 43c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sCallbackEnv = getCallbackEnv(); 44c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 45c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu JNIEnv* env = AndroidRuntime::getJNIEnv(); 46c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (sCallbackEnv != env || sCallbackEnv == NULL) return false; 47c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return true; 48c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 49c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 50c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void btavrcp_get_play_status_callback() { 51c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGI("%s", __FUNCTION__); 52c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 53c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!checkCallbackThread()) { 54c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 55c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 56c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 57c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 58c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getPlayStatus); 59c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 60c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 61c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 62c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void btavrcp_get_element_attr_callback(uint8_t num_attr, btrc_media_attr_t *p_attrs) { 63c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jintArray attrs; 64c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 65c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGI("%s", __FUNCTION__); 66c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 67c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!checkCallbackThread()) { 68c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 69c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 70c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 71c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrs = (jintArray)sCallbackEnv->NewIntArray(num_attr); 72c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!attrs) { 73c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Fail to new jintArray for attrs"); 74c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 75c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 76c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 77c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sCallbackEnv->SetIntArrayRegion(attrs, 0, num_attr, (jint *)p_attrs); 78c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getElementAttr, (jbyte)num_attr, attrs); 79c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 80c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sCallbackEnv->DeleteLocalRef(attrs); 81c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 82c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 83c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void btavrcp_register_notification_callback(btrc_event_id_t event_id, uint32_t param) { 84c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGI("%s", __FUNCTION__); 85c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 86c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!checkCallbackThread()) { 87c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 88c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 89c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 90c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 91c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sCallbackEnv->CallVoidMethod(mCallbacksObj, method_registerNotification, 92c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu (jint)event_id, (jint)param); 93c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 94c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 95c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 96ace834feb02adabd61f628c4471147aea02d939cJohn Dustatic void btavrcp_passthrough_command_callback(int id, int pressed) { 97ace834feb02adabd61f628c4471147aea02d939cJohn Du ALOGI("%s", __FUNCTION__); 98ace834feb02adabd61f628c4471147aea02d939cJohn Du 99ace834feb02adabd61f628c4471147aea02d939cJohn Du if (!checkCallbackThread()) { 100ace834feb02adabd61f628c4471147aea02d939cJohn Du ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 101ace834feb02adabd61f628c4471147aea02d939cJohn Du return; 102ace834feb02adabd61f628c4471147aea02d939cJohn Du } 103ace834feb02adabd61f628c4471147aea02d939cJohn Du 104ace834feb02adabd61f628c4471147aea02d939cJohn Du sCallbackEnv->CallVoidMethod(mCallbacksObj, method_handlePassthroughCmd, (jint)id, 105ace834feb02adabd61f628c4471147aea02d939cJohn Du (jint)pressed); 106ace834feb02adabd61f628c4471147aea02d939cJohn Du checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 107ace834feb02adabd61f628c4471147aea02d939cJohn Du} 108ace834feb02adabd61f628c4471147aea02d939cJohn Du 109c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic btrc_callbacks_t sBluetoothAvrcpCallbacks = { 110c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sizeof(sBluetoothAvrcpCallbacks), 111c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu btavrcp_get_play_status_callback, 112c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu NULL, 113c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu NULL, 114c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu NULL, 115c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu NULL, 116c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu NULL, 117c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu NULL, 118c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu btavrcp_get_element_attr_callback, 119ace834feb02adabd61f628c4471147aea02d939cJohn Du btavrcp_register_notification_callback, 120ace834feb02adabd61f628c4471147aea02d939cJohn Du btavrcp_passthrough_command_callback 121c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}; 122c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 123c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void classInitNative(JNIEnv* env, jclass clazz) { 124c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu method_getPlayStatus = 125c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->GetMethodID(clazz, "getPlayStatus", "()V"); 126c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 127c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu method_getElementAttr = 128c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->GetMethodID(clazz, "getElementAttr", "(B[I)V"); 129c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 130c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu method_registerNotification = 131c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->GetMethodID(clazz, "registerNotification", "(II)V"); 132c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 133ace834feb02adabd61f628c4471147aea02d939cJohn Du method_handlePassthroughCmd = 134ace834feb02adabd61f628c4471147aea02d939cJohn Du env->GetMethodID(clazz, "handlePassthroughCmd", "(II)V"); 135ace834feb02adabd61f628c4471147aea02d939cJohn Du 136c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGI("%s: succeeds", __FUNCTION__); 137c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 138c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 139c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void initNative(JNIEnv *env, jobject object) { 140c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu const bt_interface_t* btInf; 141c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu bt_status_t status; 142c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 143c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ( (btInf = getBluetoothInterface()) == NULL) { 144c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Bluetooth module is not loaded"); 145c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 146c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 147c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 148c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (sBluetoothAvrcpInterface !=NULL) { 149c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGW("Cleaning up Avrcp Interface before initializing..."); 150c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sBluetoothAvrcpInterface->cleanup(); 151c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sBluetoothAvrcpInterface = NULL; 152c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 153c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 154c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (mCallbacksObj != NULL) { 155c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGW("Cleaning up Avrcp callback object"); 156c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->DeleteGlobalRef(mCallbacksObj); 157c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mCallbacksObj = NULL; 158c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 159c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 160c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ( (sBluetoothAvrcpInterface = (btrc_interface_t *) 161c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu btInf->get_profile_interface(BT_PROFILE_AV_RC_ID)) == NULL) { 162c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Failed to get Bluetooth Avrcp Interface"); 163c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 164c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 165c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 166c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ( (status = sBluetoothAvrcpInterface->init(&sBluetoothAvrcpCallbacks)) != 167c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu BT_STATUS_SUCCESS) { 168c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Failed to initialize Bluetooth Avrcp, status: %d", status); 169c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sBluetoothAvrcpInterface = NULL; 170c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 171c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 172c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 173c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mCallbacksObj = env->NewGlobalRef(object); 174c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 175c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 176c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void cleanupNative(JNIEnv *env, jobject object) { 177c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu const bt_interface_t* btInf; 178c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 179c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ( (btInf = getBluetoothInterface()) == NULL) { 180c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Bluetooth module is not loaded"); 181c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return; 182c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 183c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 184c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (sBluetoothAvrcpInterface !=NULL) { 185c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sBluetoothAvrcpInterface->cleanup(); 186c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sBluetoothAvrcpInterface = NULL; 187c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 188c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 189c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (mCallbacksObj != NULL) { 190c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->DeleteGlobalRef(mCallbacksObj); 191c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mCallbacksObj = NULL; 192c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 193c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 194c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 195c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jboolean getPlayStatusRspNative(JNIEnv *env, jobject object, jint playStatus, 196c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jint songLen, jint songPos) { 197c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu bt_status_t status; 198c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 199c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); 200c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!sBluetoothAvrcpInterface) return JNI_FALSE; 201c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 202c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ((status = sBluetoothAvrcpInterface->get_play_status_rsp((btrc_play_status_t)playStatus, 203c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu songLen, songPos)) != BT_STATUS_SUCCESS) { 204c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Failed get_play_status_rsp, status: %d", status); 205c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 206c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 207c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 208c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 209c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 210c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu static jboolean getElementAttrRspNative(JNIEnv *env, jobject object, jbyte numAttr, 211c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jintArray attrIds, jobjectArray textArray) { 212c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jint *attr; 213c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu bt_status_t status; 214c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jstring text; 215c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int i; 216c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu btrc_element_attr_val_t *pAttrs = NULL; 217c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu const char* textStr; 218c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 219c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!sBluetoothAvrcpInterface) return JNI_FALSE; 220c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 221c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (numAttr > BTRC_MAX_ELEM_ATTR_SIZE) { 222c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("get_element_attr_rsp: number of attributes exceed maximum"); 223c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return JNI_FALSE; 224c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 225c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 226c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu pAttrs = new btrc_element_attr_val_t[numAttr]; 227c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!pAttrs) { 228c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("get_element_attr_rsp: not have enough memeory"); 229c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return JNI_FALSE; 230c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 231c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 232c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attr = env->GetIntArrayElements(attrIds, NULL); 233c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!attr) { 234c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu delete[] pAttrs; 235c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jniThrowIOException(env, EINVAL); 236c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return JNI_FALSE; 237c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 238c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 239c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu for (i = 0; i < numAttr; ++i) { 240c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu text = (jstring) env->GetObjectArrayElement(textArray, i); 241c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu textStr = env->GetStringUTFChars(text, NULL); 242c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!textStr) { 243c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("get_element_attr_rsp: GetStringUTFChars return NULL"); 244c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->DeleteLocalRef(text); 245c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 246c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 247885213461ae72d6db178c95fafc01cde153230dbZhihai Xu 248885213461ae72d6db178c95fafc01cde153230dbZhihai Xu pAttrs[i].attr_id = attr[i]; 249c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (strlen(textStr) >= BTRC_MAX_ATTR_STR_LEN) { 250c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("get_element_attr_rsp: string length exceed maximum"); 251885213461ae72d6db178c95fafc01cde153230dbZhihai Xu strncpy((char *)pAttrs[i].text, textStr, BTRC_MAX_ATTR_STR_LEN-1); 252885213461ae72d6db178c95fafc01cde153230dbZhihai Xu pAttrs[i].text[BTRC_MAX_ATTR_STR_LEN-1] = 0; 253885213461ae72d6db178c95fafc01cde153230dbZhihai Xu } else { 254885213461ae72d6db178c95fafc01cde153230dbZhihai Xu strcpy((char *)pAttrs[i].text, textStr); 255c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 256c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->ReleaseStringUTFChars(text, textStr); 257c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->DeleteLocalRef(text); 258c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 259c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 260c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (i < numAttr) { 261c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu delete[] pAttrs; 262c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->ReleaseIntArrayElements(attrIds, attr, 0); 263c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return JNI_FALSE; 264c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 265c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 266c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ((status = sBluetoothAvrcpInterface->get_element_attr_rsp(numAttr, pAttrs)) != 267c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu BT_STATUS_SUCCESS) { 268c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Failed get_element_attr_rsp, status: %d", status); 269c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 270c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 271c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu delete[] pAttrs; 272c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->ReleaseIntArrayElements(attrIds, attr, 0); 273c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 274c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 275c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 276c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jboolean registerNotificationRspPlayStatusNative(JNIEnv *env, jobject object, 277c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jint type, jint playStatus) { 278c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu bt_status_t status; 279c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu btrc_register_notification_t param; 280c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 281c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); 282c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!sBluetoothAvrcpInterface) return JNI_FALSE; 283c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 284c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu param.play_status = (btrc_play_status_t)playStatus; 285c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ((status = sBluetoothAvrcpInterface->register_notification_rsp(BTRC_EVT_PLAY_STATUS_CHANGED, 286c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu (btrc_notification_type_t)type, ¶m)) != BT_STATUS_SUCCESS) { 287c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Failed register_notification_rsp play status, status: %d", status); 288c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 289c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 290c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 291c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 292c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 293c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jboolean registerNotificationRspTrackChangeNative(JNIEnv *env, jobject object, 294c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jint type, jbyteArray track) { 295c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu bt_status_t status; 296c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu btrc_register_notification_t param; 297c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jbyte *trk; 298c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int i; 299c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 300c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); 301c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!sBluetoothAvrcpInterface) return JNI_FALSE; 302c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 303c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu trk = env->GetByteArrayElements(track, NULL); 304c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!trk) { 305c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu jniThrowIOException(env, EINVAL); 306c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return JNI_FALSE; 307c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 308c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 309c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu for (i = 0; i < BTRC_UID_SIZE; ++i) { 310c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu param.track[i] = trk[i]; 311c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 312c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 313c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ((status = sBluetoothAvrcpInterface->register_notification_rsp(BTRC_EVT_TRACK_CHANGE, 314c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu (btrc_notification_type_t)type, ¶m)) != BT_STATUS_SUCCESS) { 315c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ALOGE("Failed register_notification_rsp track change, status: %d", status); 316c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 317c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 318c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu env->ReleaseByteArrayElements(track, trk, 0); 319c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 320c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 321c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 322aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xustatic jboolean registerNotificationRspPlayPosNative(JNIEnv *env, jobject object, 323aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu jint type, jint playPos) { 324aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu bt_status_t status; 325aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu btrc_register_notification_t param; 326aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 327aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface); 328aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if (!sBluetoothAvrcpInterface) return JNI_FALSE; 329aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 330aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu param.song_pos = (uint32_t)playPos; 331aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if ((status = sBluetoothAvrcpInterface->register_notification_rsp(BTRC_EVT_PLAY_POS_CHANGED, 332aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu (btrc_notification_type_t)type, ¶m)) != BT_STATUS_SUCCESS) { 333aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu ALOGE("Failed register_notification_rsp play position, status: %d", status); 334aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 335aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 336aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 337aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu} 338aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 339c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic JNINativeMethod sMethods[] = { 340c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu {"classInitNative", "()V", (void *) classInitNative}, 341c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu {"initNative", "()V", (void *) initNative}, 342c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu {"cleanupNative", "()V", (void *) cleanupNative}, 343c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu {"getPlayStatusRspNative", "(III)Z", (void *) getPlayStatusRspNative}, 344c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu {"getElementAttrRspNative", "(B[I[Ljava/lang/String;)Z", (void *) getElementAttrRspNative}, 345c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu {"registerNotificationRspPlayStatusNative", "(II)Z", 346c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu (void *) registerNotificationRspPlayStatusNative}, 347c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu {"registerNotificationRspTrackChangeNative", "(I[B)Z", 348c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu (void *) registerNotificationRspTrackChangeNative}, 349aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu {"registerNotificationRspPlayPosNative", "(II)Z", 350aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu (void *) registerNotificationRspPlayPosNative}, 351c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}; 352c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 353c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuint register_com_android_bluetooth_avrcp(JNIEnv* env) 354c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu{ 355c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return jniRegisterNativeMethods(env, "com/android/bluetooth/a2dp/Avrcp", 356c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sMethods, NELEM(sMethods)); 357c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 358c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 359c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 360