com_android_bluetooth_avrcp.cpp revision 5c86abdc7875a8fae28c57e3e36a0a8eaae5cb04
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 {
2917675906064bb72fdcca75baa56cdf8bb8968d01John Dustatic jmethodID method_getRcFeatures;
30c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jmethodID method_getPlayStatus;
31c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jmethodID method_getElementAttr;
32c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jmethodID method_registerNotification;
3317675906064bb72fdcca75baa56cdf8bb8968d01John Dustatic jmethodID method_volumeChangeCallback;
34ace834feb02adabd61f628c4471147aea02d939cJohn Dustatic jmethodID method_handlePassthroughCmd;
355c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Guptastatic jmethodID method_handlePassthroughRsp;
365c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Guptastatic jmethodID method_onConnectionStateChanged;
37c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
38c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic const btrc_interface_t *sBluetoothAvrcpInterface = NULL;
39c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jobject mCallbacksObj = NULL;
40c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic JNIEnv *sCallbackEnv = NULL;
41c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
42c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic bool checkCallbackThread() {
43c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    // Always fetch the latest callbackEnv from AdapterService.
44c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    // Caching this could cause this sCallbackEnv to go out-of-sync
45c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event
46c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    // is received
47c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    sCallbackEnv = getCallbackEnv();
48c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
49c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    JNIEnv* env = AndroidRuntime::getJNIEnv();
50c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (sCallbackEnv != env || sCallbackEnv == NULL) return false;
51c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    return true;
52c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}
53c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
5417675906064bb72fdcca75baa56cdf8bb8968d01John Dustatic void btavrcp_remote_features_callback(bt_bdaddr_t* bd_addr, btrc_remote_features_t features) {
5517675906064bb72fdcca75baa56cdf8bb8968d01John Du    ALOGI("%s", __FUNCTION__);
5617675906064bb72fdcca75baa56cdf8bb8968d01John Du    jbyteArray addr;
5717675906064bb72fdcca75baa56cdf8bb8968d01John Du
5817675906064bb72fdcca75baa56cdf8bb8968d01John Du    if (!checkCallbackThread()) {
5917675906064bb72fdcca75baa56cdf8bb8968d01John Du        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
6017675906064bb72fdcca75baa56cdf8bb8968d01John Du        return;
6117675906064bb72fdcca75baa56cdf8bb8968d01John Du    }
6217675906064bb72fdcca75baa56cdf8bb8968d01John Du    addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
6317675906064bb72fdcca75baa56cdf8bb8968d01John Du    if (!addr) {
6417675906064bb72fdcca75baa56cdf8bb8968d01John Du        ALOGE("Fail to new jbyteArray bd addr for connection state");
6517675906064bb72fdcca75baa56cdf8bb8968d01John Du        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
6617675906064bb72fdcca75baa56cdf8bb8968d01John Du        return;
6717675906064bb72fdcca75baa56cdf8bb8968d01John Du    }
6817675906064bb72fdcca75baa56cdf8bb8968d01John Du
6917675906064bb72fdcca75baa56cdf8bb8968d01John Du    sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
7017675906064bb72fdcca75baa56cdf8bb8968d01John Du    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getRcFeatures, addr, (jint)features);
7117675906064bb72fdcca75baa56cdf8bb8968d01John Du    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
72fd80b9517bf8bc45257af83074114d493ba7d984Nitin Srivastava    sCallbackEnv->DeleteLocalRef(addr);
7317675906064bb72fdcca75baa56cdf8bb8968d01John Du}
7417675906064bb72fdcca75baa56cdf8bb8968d01John Du
75c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void btavrcp_get_play_status_callback() {
76c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    ALOGI("%s", __FUNCTION__);
77c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
78c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (!checkCallbackThread()) {
79c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
80c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        return;
81c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
82c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
83c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getPlayStatus);
84c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
85c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}
86c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
87c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void btavrcp_get_element_attr_callback(uint8_t num_attr, btrc_media_attr_t *p_attrs) {
88c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    jintArray attrs;
89c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
90c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    ALOGI("%s", __FUNCTION__);
91c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
92c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (!checkCallbackThread()) {
93c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
94c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        return;
95c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
96c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    attrs = (jintArray)sCallbackEnv->NewIntArray(num_attr);
97c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (!attrs) {
98c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        ALOGE("Fail to new jintArray for attrs");
99c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
100c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        return;
101c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
102c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    sCallbackEnv->SetIntArrayRegion(attrs, 0, num_attr, (jint *)p_attrs);
103c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_getElementAttr, (jbyte)num_attr, attrs);
104c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
105c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    sCallbackEnv->DeleteLocalRef(attrs);
106c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}
107c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
108c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void btavrcp_register_notification_callback(btrc_event_id_t event_id, uint32_t param) {
109c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    ALOGI("%s", __FUNCTION__);
110c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
111c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (!checkCallbackThread()) {
112c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
113c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        return;
114c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
115c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
116c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_registerNotification,
117c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu                                 (jint)event_id, (jint)param);
118c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
119c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}
120c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
12117675906064bb72fdcca75baa56cdf8bb8968d01John Dustatic void btavrcp_volume_change_callback(uint8_t volume, uint8_t ctype) {
12217675906064bb72fdcca75baa56cdf8bb8968d01John Du    ALOGI("%s", __FUNCTION__);
12317675906064bb72fdcca75baa56cdf8bb8968d01John Du
12417675906064bb72fdcca75baa56cdf8bb8968d01John Du    if (!checkCallbackThread()) {
12517675906064bb72fdcca75baa56cdf8bb8968d01John Du        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
12617675906064bb72fdcca75baa56cdf8bb8968d01John Du        return;
12717675906064bb72fdcca75baa56cdf8bb8968d01John Du    }
12817675906064bb72fdcca75baa56cdf8bb8968d01John Du
12917675906064bb72fdcca75baa56cdf8bb8968d01John Du    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_volumeChangeCallback, (jint)volume,
13017675906064bb72fdcca75baa56cdf8bb8968d01John Du                                                                             (jint)ctype);
13117675906064bb72fdcca75baa56cdf8bb8968d01John Du    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
13217675906064bb72fdcca75baa56cdf8bb8968d01John Du}
13317675906064bb72fdcca75baa56cdf8bb8968d01John Du
134ace834feb02adabd61f628c4471147aea02d939cJohn Dustatic void btavrcp_passthrough_command_callback(int id, int pressed) {
135ace834feb02adabd61f628c4471147aea02d939cJohn Du    ALOGI("%s", __FUNCTION__);
136ace834feb02adabd61f628c4471147aea02d939cJohn Du
137ace834feb02adabd61f628c4471147aea02d939cJohn Du    if (!checkCallbackThread()) {
138ace834feb02adabd61f628c4471147aea02d939cJohn Du        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
139ace834feb02adabd61f628c4471147aea02d939cJohn Du        return;
140ace834feb02adabd61f628c4471147aea02d939cJohn Du    }
141ace834feb02adabd61f628c4471147aea02d939cJohn Du
142ace834feb02adabd61f628c4471147aea02d939cJohn Du    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_handlePassthroughCmd, (jint)id,
143ace834feb02adabd61f628c4471147aea02d939cJohn Du                                                                             (jint)pressed);
144ace834feb02adabd61f628c4471147aea02d939cJohn Du    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
145ace834feb02adabd61f628c4471147aea02d939cJohn Du}
146ace834feb02adabd61f628c4471147aea02d939cJohn Du
1475c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Guptastatic void btavrcp_passthrough_response_callback(int id, int pressed) {
1485c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    ALOGI("%s", __FUNCTION__);
1495c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    ALOGI("id: %d, pressed: %d", id, pressed);
1505c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
1515c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    if (!checkCallbackThread()) {
1525c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
1535c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta        return;
1545c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    }
1555c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
1565c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_handlePassthroughRsp, (jint)id,
1575c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta                                                                             (jint)pressed);
1585c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
1595c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta}
1605c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
1615c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Guptastatic void btavrcp_connection_state_callback(int state, bt_bdaddr_t* bd_addr) {
1625c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    jbyteArray addr;
1635c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
1645c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    ALOGI("%s", __FUNCTION__);
1655c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    ALOGI("conn state: %d", state);
1665c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
1675c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    if (!checkCallbackThread()) {                                       \
1685c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
1695c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta        return;                                                         \
1705c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    }
1715c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
1725c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
1735c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    if (!addr) {
1745c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta        ALOGE("Fail to new jbyteArray bd addr for connection state");
1755c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
1765c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta        return;
1775c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    }
1785c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
1795c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
1805c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, (jint) state,
1815c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta                                 addr);
1825c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
1835c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    sCallbackEnv->DeleteLocalRef(addr);
1845c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta}
1855c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
1865c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
187c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic btrc_callbacks_t sBluetoothAvrcpCallbacks = {
188c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    sizeof(sBluetoothAvrcpCallbacks),
18917675906064bb72fdcca75baa56cdf8bb8968d01John Du    btavrcp_remote_features_callback,
190c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    btavrcp_get_play_status_callback,
191c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    NULL,
192c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    NULL,
193c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    NULL,
194c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    NULL,
195c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    NULL,
196c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    NULL,
197c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    btavrcp_get_element_attr_callback,
198ace834feb02adabd61f628c4471147aea02d939cJohn Du    btavrcp_register_notification_callback,
19917675906064bb72fdcca75baa56cdf8bb8968d01John Du    btavrcp_volume_change_callback,
2005c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    btavrcp_passthrough_command_callback,
2015c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    btavrcp_passthrough_response_callback,
2025c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    btavrcp_connection_state_callback
203c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu};
204c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
205c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void classInitNative(JNIEnv* env, jclass clazz) {
20617675906064bb72fdcca75baa56cdf8bb8968d01John Du    method_getRcFeatures =
20717675906064bb72fdcca75baa56cdf8bb8968d01John Du        env->GetMethodID(clazz, "getRcFeatures", "([BI)V");
208c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    method_getPlayStatus =
209c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        env->GetMethodID(clazz, "getPlayStatus", "()V");
210c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
211c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    method_getElementAttr =
212c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        env->GetMethodID(clazz, "getElementAttr", "(B[I)V");
213c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
214c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    method_registerNotification =
215c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        env->GetMethodID(clazz, "registerNotification", "(II)V");
216c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
21717675906064bb72fdcca75baa56cdf8bb8968d01John Du    method_volumeChangeCallback =
21817675906064bb72fdcca75baa56cdf8bb8968d01John Du        env->GetMethodID(clazz, "volumeChangeCallback", "(II)V");
21917675906064bb72fdcca75baa56cdf8bb8968d01John Du
220ace834feb02adabd61f628c4471147aea02d939cJohn Du    method_handlePassthroughCmd =
221ace834feb02adabd61f628c4471147aea02d939cJohn Du        env->GetMethodID(clazz, "handlePassthroughCmd", "(II)V");
222ace834feb02adabd61f628c4471147aea02d939cJohn Du
2235c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    method_handlePassthroughRsp =
2245c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta        env->GetMethodID(clazz, "handlePassthroughRsp", "(II)V");
2255c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
2265c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    method_onConnectionStateChanged =
2275c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta        env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V");
2285c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
229c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    ALOGI("%s: succeeds", __FUNCTION__);
230c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}
231c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
232c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void initNative(JNIEnv *env, jobject object) {
233c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    const bt_interface_t* btInf;
234c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    bt_status_t status;
235c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
236c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if ( (btInf = getBluetoothInterface()) == NULL) {
237c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        ALOGE("Bluetooth module is not loaded");
238c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        return;
239c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
240c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
241c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (sBluetoothAvrcpInterface !=NULL) {
242c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu         ALOGW("Cleaning up Avrcp Interface before initializing...");
243c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu         sBluetoothAvrcpInterface->cleanup();
244c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu         sBluetoothAvrcpInterface = NULL;
245c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
246c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
247c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (mCallbacksObj != NULL) {
248c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu         ALOGW("Cleaning up Avrcp callback object");
249c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu         env->DeleteGlobalRef(mCallbacksObj);
250c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu         mCallbacksObj = NULL;
251c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
252c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
253c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if ( (sBluetoothAvrcpInterface = (btrc_interface_t *)
254c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu          btInf->get_profile_interface(BT_PROFILE_AV_RC_ID)) == NULL) {
255c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        ALOGE("Failed to get Bluetooth Avrcp Interface");
256c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        return;
257c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
258c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
259c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if ( (status = sBluetoothAvrcpInterface->init(&sBluetoothAvrcpCallbacks)) !=
260c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu         BT_STATUS_SUCCESS) {
261c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        ALOGE("Failed to initialize Bluetooth Avrcp, status: %d", status);
262c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        sBluetoothAvrcpInterface = NULL;
263c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        return;
264c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
265c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
266c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    mCallbacksObj = env->NewGlobalRef(object);
267c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}
268c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
269c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic void cleanupNative(JNIEnv *env, jobject object) {
270c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    const bt_interface_t* btInf;
271c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
272c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if ( (btInf = getBluetoothInterface()) == NULL) {
273c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        ALOGE("Bluetooth module is not loaded");
274c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        return;
275c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
276c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
277c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (sBluetoothAvrcpInterface !=NULL) {
278c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        sBluetoothAvrcpInterface->cleanup();
279c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        sBluetoothAvrcpInterface = NULL;
280c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
281c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
282c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (mCallbacksObj != NULL) {
283c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        env->DeleteGlobalRef(mCallbacksObj);
284c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        mCallbacksObj = NULL;
285c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
286c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}
287c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
288c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jboolean getPlayStatusRspNative(JNIEnv *env, jobject object, jint playStatus,
289c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu                                       jint songLen, jint songPos) {
290c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    bt_status_t status;
291c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
292c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface);
293c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (!sBluetoothAvrcpInterface) return JNI_FALSE;
294c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
295c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if ((status = sBluetoothAvrcpInterface->get_play_status_rsp((btrc_play_status_t)playStatus,
296c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu                                            songLen, songPos)) != BT_STATUS_SUCCESS) {
297c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        ALOGE("Failed get_play_status_rsp, status: %d", status);
298c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
299c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
300c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
301c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}
302c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
303c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu  static jboolean getElementAttrRspNative(JNIEnv *env, jobject object, jbyte numAttr,
304c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu                                          jintArray attrIds, jobjectArray textArray) {
305c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    jint *attr;
306c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    bt_status_t status;
307c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    jstring text;
308c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    int i;
309c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    btrc_element_attr_val_t *pAttrs = NULL;
310c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    const char* textStr;
311c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
312c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (!sBluetoothAvrcpInterface) return JNI_FALSE;
313c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
314c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (numAttr > BTRC_MAX_ELEM_ATTR_SIZE) {
315c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        ALOGE("get_element_attr_rsp: number of attributes exceed maximum");
316c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        return JNI_FALSE;
317c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
318c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
319c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    pAttrs = new btrc_element_attr_val_t[numAttr];
320c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (!pAttrs) {
321c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        ALOGE("get_element_attr_rsp: not have enough memeory");
322c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        return JNI_FALSE;
323c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
324c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
325c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    attr = env->GetIntArrayElements(attrIds, NULL);
326c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (!attr) {
327c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        delete[] pAttrs;
328c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        jniThrowIOException(env, EINVAL);
329c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        return JNI_FALSE;
330c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
331c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
332c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    for (i = 0; i < numAttr; ++i) {
333c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        text = (jstring) env->GetObjectArrayElement(textArray, i);
334c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        textStr = env->GetStringUTFChars(text, NULL);
335c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        if (!textStr) {
336c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu            ALOGE("get_element_attr_rsp: GetStringUTFChars return NULL");
337c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu            env->DeleteLocalRef(text);
338c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu            break;
339c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        }
340885213461ae72d6db178c95fafc01cde153230dbZhihai Xu
341885213461ae72d6db178c95fafc01cde153230dbZhihai Xu        pAttrs[i].attr_id = attr[i];
342c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        if (strlen(textStr) >= BTRC_MAX_ATTR_STR_LEN) {
343c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu            ALOGE("get_element_attr_rsp: string length exceed maximum");
344885213461ae72d6db178c95fafc01cde153230dbZhihai Xu            strncpy((char *)pAttrs[i].text, textStr, BTRC_MAX_ATTR_STR_LEN-1);
345885213461ae72d6db178c95fafc01cde153230dbZhihai Xu            pAttrs[i].text[BTRC_MAX_ATTR_STR_LEN-1] = 0;
346885213461ae72d6db178c95fafc01cde153230dbZhihai Xu        } else {
347885213461ae72d6db178c95fafc01cde153230dbZhihai Xu            strcpy((char *)pAttrs[i].text, textStr);
348c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        }
349c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        env->ReleaseStringUTFChars(text, textStr);
350c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        env->DeleteLocalRef(text);
351c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
352c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
353c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (i < numAttr) {
354c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        delete[] pAttrs;
355c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        env->ReleaseIntArrayElements(attrIds, attr, 0);
356c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        return JNI_FALSE;
357c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
358c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
359c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if ((status = sBluetoothAvrcpInterface->get_element_attr_rsp(numAttr, pAttrs)) !=
360c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        BT_STATUS_SUCCESS) {
361c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        ALOGE("Failed get_element_attr_rsp, status: %d", status);
362c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
363c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
364c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    delete[] pAttrs;
365c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    env->ReleaseIntArrayElements(attrIds, attr, 0);
366c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
367c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}
368c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
369c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jboolean registerNotificationRspPlayStatusNative(JNIEnv *env, jobject object,
370c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu                                                        jint type, jint playStatus) {
371c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    bt_status_t status;
372c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    btrc_register_notification_t param;
373c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
374c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface);
375c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (!sBluetoothAvrcpInterface) return JNI_FALSE;
376c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
377c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    param.play_status = (btrc_play_status_t)playStatus;
378c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if ((status = sBluetoothAvrcpInterface->register_notification_rsp(BTRC_EVT_PLAY_STATUS_CHANGED,
379c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu                  (btrc_notification_type_t)type, &param)) != BT_STATUS_SUCCESS) {
380c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        ALOGE("Failed register_notification_rsp play status, status: %d", status);
381c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
382c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
383c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
384c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}
385c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
386c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic jboolean registerNotificationRspTrackChangeNative(JNIEnv *env, jobject object,
387c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu                                                         jint type, jbyteArray track) {
388c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    bt_status_t status;
389c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    btrc_register_notification_t param;
390c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    jbyte *trk;
391c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    int i;
392c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
393c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface);
394c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (!sBluetoothAvrcpInterface) return JNI_FALSE;
395c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
396c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    trk = env->GetByteArrayElements(track, NULL);
397c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if (!trk) {
398c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        jniThrowIOException(env, EINVAL);
399c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        return JNI_FALSE;
400c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
401c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
402c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    for (i = 0; i < BTRC_UID_SIZE; ++i) {
403c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu      param.track[i] = trk[i];
404c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
405c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
406c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    if ((status = sBluetoothAvrcpInterface->register_notification_rsp(BTRC_EVT_TRACK_CHANGE,
407c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu                  (btrc_notification_type_t)type, &param)) != BT_STATUS_SUCCESS) {
408c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu        ALOGE("Failed register_notification_rsp track change, status: %d", status);
409c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    }
410c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
411c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    env->ReleaseByteArrayElements(track, trk, 0);
412c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
413c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}
414c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
415aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xustatic jboolean registerNotificationRspPlayPosNative(JNIEnv *env, jobject object,
416aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu                                                        jint type, jint playPos) {
417aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu    bt_status_t status;
418aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu    btrc_register_notification_t param;
419aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu
420aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu    ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface);
421aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu    if (!sBluetoothAvrcpInterface) return JNI_FALSE;
422aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu
423aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu    param.song_pos = (uint32_t)playPos;
424aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu    if ((status = sBluetoothAvrcpInterface->register_notification_rsp(BTRC_EVT_PLAY_POS_CHANGED,
425aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu                  (btrc_notification_type_t)type, &param)) != BT_STATUS_SUCCESS) {
426aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu        ALOGE("Failed register_notification_rsp play position, status: %d", status);
427aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu    }
428aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu
429aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu    return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
430aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu}
431aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu
43217675906064bb72fdcca75baa56cdf8bb8968d01John Dustatic jboolean setVolumeNative(JNIEnv *env, jobject object, jint volume) {
43317675906064bb72fdcca75baa56cdf8bb8968d01John Du    bt_status_t status;
43417675906064bb72fdcca75baa56cdf8bb8968d01John Du
43517675906064bb72fdcca75baa56cdf8bb8968d01John Du    //TODO: delete test code
43617675906064bb72fdcca75baa56cdf8bb8968d01John Du    ALOGI("%s: jint: %d, uint8_t: %u", __FUNCTION__, volume, (uint8_t) volume);
43717675906064bb72fdcca75baa56cdf8bb8968d01John Du
43817675906064bb72fdcca75baa56cdf8bb8968d01John Du    ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface);
43917675906064bb72fdcca75baa56cdf8bb8968d01John Du    if (!sBluetoothAvrcpInterface) return JNI_FALSE;
44017675906064bb72fdcca75baa56cdf8bb8968d01John Du
44117675906064bb72fdcca75baa56cdf8bb8968d01John Du    if ((status = sBluetoothAvrcpInterface->set_volume((uint8_t)volume)) != BT_STATUS_SUCCESS) {
44217675906064bb72fdcca75baa56cdf8bb8968d01John Du        ALOGE("Failed set_volume, status: %d", status);
44317675906064bb72fdcca75baa56cdf8bb8968d01John Du    }
44417675906064bb72fdcca75baa56cdf8bb8968d01John Du
44517675906064bb72fdcca75baa56cdf8bb8968d01John Du    return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
44617675906064bb72fdcca75baa56cdf8bb8968d01John Du}
44717675906064bb72fdcca75baa56cdf8bb8968d01John Du
4485c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Guptastatic jboolean sendPassThroughCommandNative(JNIEnv *env, jobject object,
4495c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta                                                    jint key_code, jint key_state) {
4505c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    bt_status_t status;
4515c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
4525c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    if (!sBluetoothAvrcpInterface) return JNI_FALSE;
4535c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
4545c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    ALOGI("%s: sBluetoothAvrcpInterface: %p", __FUNCTION__, sBluetoothAvrcpInterface);
4555c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
4565c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    ALOGI("key_code: %d, key_state: %d", key_code, key_state);
4575c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
4585c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    if ((status = sBluetoothAvrcpInterface->send_pass_through_cmd((uint8_t)key_code,
4595c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta                                        (uint8_t)key_state))!= BT_STATUS_SUCCESS) {
4605c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta        ALOGE("Failed sending passthru command, status: %d", status);
4615c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    }
4625c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
4635c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
4645c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta}
4655c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta
466c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xustatic JNINativeMethod sMethods[] = {
467c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    {"classInitNative", "()V", (void *) classInitNative},
468c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    {"initNative", "()V", (void *) initNative},
469c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    {"cleanupNative", "()V", (void *) cleanupNative},
470c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    {"getPlayStatusRspNative", "(III)Z", (void *) getPlayStatusRspNative},
471c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    {"getElementAttrRspNative", "(B[I[Ljava/lang/String;)Z", (void *) getElementAttrRspNative},
472c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    {"registerNotificationRspPlayStatusNative", "(II)Z",
473c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu     (void *) registerNotificationRspPlayStatusNative},
474c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    {"registerNotificationRspTrackChangeNative", "(I[B)Z",
475c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu     (void *) registerNotificationRspTrackChangeNative},
476aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu    {"registerNotificationRspPlayPosNative", "(II)Z",
477aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu     (void *) registerNotificationRspPlayPosNative},
47817675906064bb72fdcca75baa56cdf8bb8968d01John Du    {"setVolumeNative", "(I)Z",
4795c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta     (void *) setVolumeNative},
4805c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta    {"sendPassThroughCommandNative", "(II)Z",
4815c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta     (void *) sendPassThroughCommandNative},
482c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu};
483c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
484c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuint register_com_android_bluetooth_avrcp(JNIEnv* env)
485c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu{
486c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu    return jniRegisterNativeMethods(env, "com/android/bluetooth/a2dp/Avrcp",
487c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu                                    sMethods, NELEM(sMethods));
488c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}
489c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu
490c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu}
491