blob: 51af2bf3fdd74fd8a3dafc159e3f5f2885b0bef4 [file] [log] [blame]
Hemant Guptaaebc7262013-08-19 18:54:29 +05301/*
2 * Copyright (c) 2014 The Android Open Source Project
3 * Copyright (C) 2012 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Mike Lockwood8d536f32014-06-12 12:07:01 -070018#define LOG_TAG "BluetoothHeadsetClientServiceJni"
Hemant Guptaaebc7262013-08-19 18:54:29 +053019#define LOG_NDEBUG 0
20
Marie Janssendbd48b52016-12-06 09:57:09 -080021#include "android_runtime/AndroidRuntime.h"
Hemant Guptaaebc7262013-08-19 18:54:29 +053022#include "com_android_bluetooth.h"
23#include "hardware/bt_hf_client.h"
24#include "utils/Log.h"
Hemant Guptaaebc7262013-08-19 18:54:29 +053025
Hemant Guptaaebc7262013-08-19 18:54:29 +053026namespace android {
27
Marie Janssendbd48b52016-12-06 09:57:09 -080028static bthf_client_interface_t* sBluetoothHfpClientInterface = NULL;
Hemant Guptaaebc7262013-08-19 18:54:29 +053029static jobject mCallbacksObj = NULL;
Hemant Guptaaebc7262013-08-19 18:54:29 +053030
31static jmethodID method_onConnectionStateChanged;
32static jmethodID method_onAudioStateChanged;
33static jmethodID method_onVrStateChanged;
34static jmethodID method_onNetworkState;
35static jmethodID method_onNetworkRoaming;
36static jmethodID method_onNetworkSignal;
37static jmethodID method_onBatteryLevel;
38static jmethodID method_onCurrentOperator;
39static jmethodID method_onCall;
40static jmethodID method_onCallSetup;
41static jmethodID method_onCallHeld;
42static jmethodID method_onRespAndHold;
43static jmethodID method_onClip;
44static jmethodID method_onCallWaiting;
45static jmethodID method_onCurrentCalls;
46static jmethodID method_onVolumeChange;
47static jmethodID method_onCmdResult;
48static jmethodID method_onSubscriberInfo;
49static jmethodID method_onInBandRing;
50static jmethodID method_onLastVoiceTagNumber;
51static jmethodID method_onRingIndication;
52
Jakub Pawlowskicb399252017-06-24 17:27:01 -070053static jbyteArray marshall_bda(const RawAddress* bd_addr) {
Andre Eisenbach2116dbf2017-03-17 04:47:41 +000054 CallbackEnv sCallbackEnv(__func__);
55 if (!sCallbackEnv.valid()) return NULL;
56
Jakub Pawlowskicb399252017-06-24 17:27:01 -070057 jbyteArray addr = sCallbackEnv->NewByteArray(sizeof(RawAddress));
Andre Eisenbach2116dbf2017-03-17 04:47:41 +000058 if (!addr) {
59 ALOGE("Fail to new jbyteArray bd addr");
60 return NULL;
61 }
Jakub Pawlowskicb399252017-06-24 17:27:01 -070062 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(RawAddress),
Andre Eisenbach2116dbf2017-03-17 04:47:41 +000063 (jbyte*)bd_addr);
64 return addr;
65}
66
Jakub Pawlowskicb399252017-06-24 17:27:01 -070067static void connection_state_cb(const RawAddress* bd_addr,
Sanket Agarwalef3a3b52016-11-28 15:53:06 -080068 bthf_client_connection_state_t state,
69 unsigned int peer_feat,
70 unsigned int chld_feat) {
Marie Janssendbd48b52016-12-06 09:57:09 -080071 CallbackEnv sCallbackEnv(__func__);
72 if (!sCallbackEnv.valid()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +053073
Andre Eisenbach2116dbf2017-03-17 04:47:41 +000074 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -070075 if (!addr.get()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +053076
Sanket Agarwal84f977c2016-12-14 14:09:38 -080077 ALOGD("%s: state %d peer_feat %d chld_feat %d", __func__, state, peer_feat, chld_feat);
Marie Janssendbd48b52016-12-06 09:57:09 -080078 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged,
79 (jint)state, (jint)peer_feat, (jint)chld_feat,
Marie Janssen479b3482016-10-11 13:54:41 -070080 addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +053081}
82
Jakub Pawlowskicb399252017-06-24 17:27:01 -070083static void audio_state_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -080084 bthf_client_audio_state_t state) {
85 CallbackEnv sCallbackEnv(__func__);
86 if (!sCallbackEnv.valid()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +053087
Andre Eisenbach2116dbf2017-03-17 04:47:41 +000088 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -070089 if (!addr.get()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +053090
Marie Janssendbd48b52016-12-06 09:57:09 -080091 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged,
Marie Janssen479b3482016-10-11 13:54:41 -070092 (jint)state, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +053093}
94
Jakub Pawlowskicb399252017-06-24 17:27:01 -070095static void vr_cmd_cb(const RawAddress* bd_addr, bthf_client_vr_state_t state) {
Marie Janssendbd48b52016-12-06 09:57:09 -080096 CallbackEnv sCallbackEnv(__func__);
97 if (!sCallbackEnv.valid()) return;
Joseph Pirozzoa4cca002017-10-06 14:04:22 -070098
99 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
100 if (!addr.get()) return;
101
Marie Janssendbd48b52016-12-06 09:57:09 -0800102 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVrStateChanged,
Joseph Pirozzoa4cca002017-10-06 14:04:22 -0700103 (jint)state, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530104}
105
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700106static void network_state_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800107 bthf_client_network_state_t state) {
108 CallbackEnv sCallbackEnv(__func__);
109 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800110
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000111 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700112 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800113
Marie Janssendbd48b52016-12-06 09:57:09 -0800114 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNetworkState,
Marie Janssen479b3482016-10-11 13:54:41 -0700115 (jint)state, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530116}
117
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700118static void network_roaming_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800119 bthf_client_service_type_t type) {
120 CallbackEnv sCallbackEnv(__func__);
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800121
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000122 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700123 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800124
Marie Janssendbd48b52016-12-06 09:57:09 -0800125 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNetworkRoaming,
Marie Janssen479b3482016-10-11 13:54:41 -0700126 (jint)type, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530127}
128
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700129static void network_signal_cb(const RawAddress* bd_addr, int signal) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800130 CallbackEnv sCallbackEnv(__func__);
131 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800132
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000133 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700134 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800135
Marie Janssendbd48b52016-12-06 09:57:09 -0800136 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNetworkSignal,
Marie Janssen479b3482016-10-11 13:54:41 -0700137 (jint)signal, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530138}
139
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700140static void battery_level_cb(const RawAddress* bd_addr, int level) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800141 CallbackEnv sCallbackEnv(__func__);
142 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800143
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000144 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700145 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800146
Marie Janssendbd48b52016-12-06 09:57:09 -0800147 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onBatteryLevel,
Marie Janssen479b3482016-10-11 13:54:41 -0700148 (jint)level, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530149}
150
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700151static void current_operator_cb(const RawAddress* bd_addr, const char* name) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800152 CallbackEnv sCallbackEnv(__func__);
153 if (!sCallbackEnv.valid()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530154
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000155 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700156 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800157
Marie Janssen479b3482016-10-11 13:54:41 -0700158 ScopedLocalRef<jstring> js_name(sCallbackEnv.get(),
159 sCallbackEnv->NewStringUTF(name));
Marie Janssendbd48b52016-12-06 09:57:09 -0800160 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCurrentOperator,
Marie Janssen479b3482016-10-11 13:54:41 -0700161 js_name.get(), addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530162}
163
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700164static void call_cb(const RawAddress* bd_addr, bthf_client_call_t call) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800165 CallbackEnv sCallbackEnv(__func__);
166 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800167
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000168 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700169 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800170
Marie Janssen479b3482016-10-11 13:54:41 -0700171 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCall, (jint)call,
172 addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530173}
174
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700175static void callsetup_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800176 bthf_client_callsetup_t callsetup) {
177 CallbackEnv sCallbackEnv(__func__);
178 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800179
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000180 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700181 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800182
Marie Janssen19ec7832017-02-22 07:26:34 -0800183 ALOGD("callsetup_cb bdaddr %02x:%02x:%02x:%02x:%02x:%02x",
184 bd_addr->address[0], bd_addr->address[1], bd_addr->address[2],
185 bd_addr->address[3], bd_addr->address[4], bd_addr->address[5]);
Marie Janssen479b3482016-10-11 13:54:41 -0700186
Marie Janssendbd48b52016-12-06 09:57:09 -0800187 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallSetup,
Marie Janssen479b3482016-10-11 13:54:41 -0700188 (jint)callsetup, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530189}
190
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700191static void callheld_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800192 bthf_client_callheld_t callheld) {
193 CallbackEnv sCallbackEnv(__func__);
194 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800195
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000196 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700197 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800198
Marie Janssen479b3482016-10-11 13:54:41 -0700199 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallHeld, (jint)callheld,
200 addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530201}
202
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700203static void resp_and_hold_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800204 bthf_client_resp_and_hold_t resp_and_hold) {
205 CallbackEnv sCallbackEnv(__func__);
206 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800207
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000208 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700209 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800210
Marie Janssendbd48b52016-12-06 09:57:09 -0800211 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRespAndHold,
Marie Janssen479b3482016-10-11 13:54:41 -0700212 (jint)resp_and_hold, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530213}
214
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700215static void clip_cb(const RawAddress* bd_addr, const char* number) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800216 CallbackEnv sCallbackEnv(__func__);
217 if (!sCallbackEnv.valid()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530218
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000219 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700220 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800221
Marie Janssen479b3482016-10-11 13:54:41 -0700222 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
223 sCallbackEnv->NewStringUTF(number));
224 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClip, js_number.get(),
225 addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530226}
227
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700228static void call_waiting_cb(const RawAddress* bd_addr, const char* number) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800229 CallbackEnv sCallbackEnv(__func__);
230 if (!sCallbackEnv.valid()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530231
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000232 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700233 if (!addr.get()) return;
234 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
235 sCallbackEnv->NewStringUTF(number));
236 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallWaiting,
237 js_number.get(), addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530238}
239
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700240static void current_calls_cb(const RawAddress* bd_addr, int index,
Marie Janssendbd48b52016-12-06 09:57:09 -0800241 bthf_client_call_direction_t dir,
242 bthf_client_call_state_t state,
243 bthf_client_call_mpty_type_t mpty,
244 const char* number) {
245 CallbackEnv sCallbackEnv(__func__);
246 if (!sCallbackEnv.valid()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530247
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000248 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700249 if (!addr.get()) return;
250 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
251 sCallbackEnv->NewStringUTF(number));
Marie Janssendbd48b52016-12-06 09:57:09 -0800252 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCurrentCalls, index, dir,
Marie Janssen479b3482016-10-11 13:54:41 -0700253 state, mpty, js_number.get(), addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530254}
255
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700256static void volume_change_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800257 bthf_client_volume_type_t type, int volume) {
258 CallbackEnv sCallbackEnv(__func__);
259 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800260
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000261 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700262 if (!addr.get()) return;
Marie Janssendbd48b52016-12-06 09:57:09 -0800263 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeChange, (jint)type,
Marie Janssen479b3482016-10-11 13:54:41 -0700264 (jint)volume, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530265}
266
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700267static void cmd_complete_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800268 bthf_client_cmd_complete_t type, int cme) {
269 CallbackEnv sCallbackEnv(__func__);
270 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800271
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000272 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700273 if (!addr.get()) return;
Marie Janssendbd48b52016-12-06 09:57:09 -0800274 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCmdResult, (jint)type,
Marie Janssen479b3482016-10-11 13:54:41 -0700275 (jint)cme, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530276}
277
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700278static void subscriber_info_cb(const RawAddress* bd_addr, const char* name,
Marie Janssendbd48b52016-12-06 09:57:09 -0800279 bthf_client_subscriber_service_type_t type) {
280 CallbackEnv sCallbackEnv(__func__);
281 if (!sCallbackEnv.valid()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530282
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000283 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700284 if (!addr.get()) return;
285 ScopedLocalRef<jstring> js_name(sCallbackEnv.get(),
286 sCallbackEnv->NewStringUTF(name));
287 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSubscriberInfo,
288 js_name.get(), (jint)type, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530289}
290
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700291static void in_band_ring_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800292 bthf_client_in_band_ring_state_t in_band) {
293 CallbackEnv sCallbackEnv(__func__);
294 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800295
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000296 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700297 if (!addr.get()) return;
Marie Janssendbd48b52016-12-06 09:57:09 -0800298 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onInBandRing,
Marie Janssen479b3482016-10-11 13:54:41 -0700299 (jint)in_band, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530300}
301
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700302static void last_voice_tag_number_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800303 const char* number) {
304 CallbackEnv sCallbackEnv(__func__);
305 if (!sCallbackEnv.valid()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530306
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000307 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700308 if (!addr.get()) return;
309 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
310 sCallbackEnv->NewStringUTF(number));
Marie Janssendbd48b52016-12-06 09:57:09 -0800311 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onLastVoiceTagNumber,
Marie Janssen479b3482016-10-11 13:54:41 -0700312 js_number.get(), addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530313}
314
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700315static void ring_indication_cb(const RawAddress* bd_addr) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800316 CallbackEnv sCallbackEnv(__func__);
317 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800318
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000319 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700320 if (!addr.get()) return;
321 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRingIndication,
322 addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530323}
324
325static bthf_client_callbacks_t sBluetoothHfpClientCallbacks = {
326 sizeof(sBluetoothHfpClientCallbacks),
327 connection_state_cb,
328 audio_state_cb,
329 vr_cmd_cb,
330 network_state_cb,
331 network_roaming_cb,
332 network_signal_cb,
333 battery_level_cb,
334 current_operator_cb,
335 call_cb,
336 callsetup_cb,
337 callheld_cb,
338 resp_and_hold_cb,
339 clip_cb,
340 call_waiting_cb,
341 current_calls_cb,
342 volume_change_cb,
343 cmd_complete_cb,
344 subscriber_info_cb,
345 in_band_ring_cb,
346 last_voice_tag_number_cb,
347 ring_indication_cb,
348};
349
350static void classInitNative(JNIEnv* env, jclass clazz) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800351 method_onConnectionStateChanged =
352 env->GetMethodID(clazz, "onConnectionStateChanged", "(III[B)V");
353 method_onAudioStateChanged =
354 env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V");
Joseph Pirozzoa4cca002017-10-06 14:04:22 -0700355 method_onVrStateChanged =
356 env->GetMethodID(clazz, "onVrStateChanged", "(I[B)V");
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800357 method_onNetworkState = env->GetMethodID(clazz, "onNetworkState", "(I[B)V");
358 method_onNetworkRoaming = env->GetMethodID(clazz, "onNetworkRoaming", "(I[B)V");
359 method_onNetworkSignal = env->GetMethodID(clazz, "onNetworkSignal", "(I[B)V");
360 method_onBatteryLevel = env->GetMethodID(clazz, "onBatteryLevel", "(I[B)V");
Marie Janssendbd48b52016-12-06 09:57:09 -0800361 method_onCurrentOperator =
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800362 env->GetMethodID(clazz, "onCurrentOperator", "(Ljava/lang/String;[B)V");
363 method_onCall = env->GetMethodID(clazz, "onCall", "(I[B)V");
364 method_onCallSetup = env->GetMethodID(clazz, "onCallSetup", "(I[B)V");
365 method_onCallHeld = env->GetMethodID(clazz, "onCallHeld", "(I[B)V");
366 method_onRespAndHold = env->GetMethodID(clazz, "onRespAndHold", "(I[B)V");
367 method_onClip = env->GetMethodID(clazz, "onClip", "(Ljava/lang/String;[B)V");
Marie Janssendbd48b52016-12-06 09:57:09 -0800368 method_onCallWaiting =
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800369 env->GetMethodID(clazz, "onCallWaiting", "(Ljava/lang/String;[B)V");
Marie Janssendbd48b52016-12-06 09:57:09 -0800370 method_onCurrentCalls =
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800371 env->GetMethodID(clazz, "onCurrentCalls", "(IIIILjava/lang/String;[B)V");
372 method_onVolumeChange = env->GetMethodID(clazz, "onVolumeChange", "(II[B)V");
373 method_onCmdResult = env->GetMethodID(clazz, "onCmdResult", "(II[B)V");
Marie Janssendbd48b52016-12-06 09:57:09 -0800374 method_onSubscriberInfo =
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800375 env->GetMethodID(clazz, "onSubscriberInfo", "(Ljava/lang/String;I[B)V");
376 method_onInBandRing = env->GetMethodID(clazz, "onInBandRing", "(I[B)V");
Marie Janssendbd48b52016-12-06 09:57:09 -0800377 method_onLastVoiceTagNumber =
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800378 env->GetMethodID(clazz, "onLastVoiceTagNumber", "(Ljava/lang/String;[B)V");
379 method_onRingIndication = env->GetMethodID(clazz, "onRingIndication", "([B)V");
Hemant Guptaaebc7262013-08-19 18:54:29 +0530380
Marie Janssendbd48b52016-12-06 09:57:09 -0800381 ALOGI("%s succeeds", __func__);
Hemant Guptaaebc7262013-08-19 18:54:29 +0530382}
383
Marie Janssendbd48b52016-12-06 09:57:09 -0800384static void initializeNative(JNIEnv* env, jobject object) {
Sanket Agarwal727dc792017-01-24 14:59:31 -0800385 ALOGD("%s: HfpClient", __func__);
Marie Janssendbd48b52016-12-06 09:57:09 -0800386 const bt_interface_t* btInf = getBluetoothInterface();
387 if (btInf == NULL) {
388 ALOGE("Bluetooth module is not loaded");
389 return;
390 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530391
Marie Janssendbd48b52016-12-06 09:57:09 -0800392 if (sBluetoothHfpClientInterface != NULL) {
393 ALOGW("Cleaning up Bluetooth HFP Client Interface before initializing");
394 sBluetoothHfpClientInterface->cleanup();
395 sBluetoothHfpClientInterface = NULL;
396 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530397
Marie Janssendbd48b52016-12-06 09:57:09 -0800398 if (mCallbacksObj != NULL) {
399 ALOGW("Cleaning up Bluetooth HFP Client callback object");
400 env->DeleteGlobalRef(mCallbacksObj);
401 mCallbacksObj = NULL;
402 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530403
Marie Janssendbd48b52016-12-06 09:57:09 -0800404 sBluetoothHfpClientInterface =
405 (bthf_client_interface_t*)btInf->get_profile_interface(
406 BT_PROFILE_HANDSFREE_CLIENT_ID);
407 if (sBluetoothHfpClientInterface == NULL) {
408 ALOGE("Failed to get Bluetooth HFP Client Interface");
409 return;
410 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530411
Marie Janssendbd48b52016-12-06 09:57:09 -0800412 bt_status_t status =
413 sBluetoothHfpClientInterface->init(&sBluetoothHfpClientCallbacks);
414 if (status != BT_STATUS_SUCCESS) {
415 ALOGE("Failed to initialize Bluetooth HFP Client, status: %d", status);
416 sBluetoothHfpClientInterface = NULL;
417 return;
418 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530419
Marie Janssendbd48b52016-12-06 09:57:09 -0800420 mCallbacksObj = env->NewGlobalRef(object);
Hemant Guptaaebc7262013-08-19 18:54:29 +0530421}
422
Marie Janssendbd48b52016-12-06 09:57:09 -0800423static void cleanupNative(JNIEnv* env, jobject object) {
424 const bt_interface_t* btInf = getBluetoothInterface();
425 if (btInf == NULL) {
426 ALOGE("Bluetooth module is not loaded");
427 return;
428 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530429
Marie Janssendbd48b52016-12-06 09:57:09 -0800430 if (sBluetoothHfpClientInterface != NULL) {
431 ALOGW("Cleaning up Bluetooth HFP Client Interface...");
432 sBluetoothHfpClientInterface->cleanup();
433 sBluetoothHfpClientInterface = NULL;
434 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530435
Marie Janssendbd48b52016-12-06 09:57:09 -0800436 if (mCallbacksObj != NULL) {
437 ALOGW("Cleaning up Bluetooth HFP Client callback object");
438 env->DeleteGlobalRef(mCallbacksObj);
439 mCallbacksObj = NULL;
440 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530441}
442
Marie Janssendbd48b52016-12-06 09:57:09 -0800443static jboolean connectNative(JNIEnv* env, jobject object, jbyteArray address) {
444 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530445
Marie Janssendbd48b52016-12-06 09:57:09 -0800446 jbyte* addr = env->GetByteArrayElements(address, NULL);
447 if (!addr) {
448 jniThrowIOException(env, EINVAL);
449 return JNI_FALSE;
450 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530451
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700452 bt_status_t status = sBluetoothHfpClientInterface->connect((RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800453 if (status != BT_STATUS_SUCCESS) {
454 ALOGE("Failed AG connection, status: %d", status);
455 }
456 env->ReleaseByteArrayElements(address, addr, 0);
457 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530458}
459
Marie Janssendbd48b52016-12-06 09:57:09 -0800460static jboolean disconnectNative(JNIEnv* env, jobject object,
461 jbyteArray address) {
462 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530463
Marie Janssendbd48b52016-12-06 09:57:09 -0800464 jbyte* addr = env->GetByteArrayElements(address, NULL);
465 if (!addr) {
466 jniThrowIOException(env, EINVAL);
467 return JNI_FALSE;
468 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530469
Marie Janssendbd48b52016-12-06 09:57:09 -0800470 bt_status_t status =
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700471 sBluetoothHfpClientInterface->disconnect((const RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800472 if (status != BT_STATUS_SUCCESS) {
473 ALOGE("Failed AG disconnection, status: %d", status);
474 }
475 env->ReleaseByteArrayElements(address, addr, 0);
476 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530477}
478
Marie Janssendbd48b52016-12-06 09:57:09 -0800479static jboolean connectAudioNative(JNIEnv* env, jobject object,
480 jbyteArray address) {
481 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530482
Marie Janssendbd48b52016-12-06 09:57:09 -0800483 jbyte* addr = env->GetByteArrayElements(address, NULL);
484 if (!addr) {
485 jniThrowIOException(env, EINVAL);
486 return JNI_FALSE;
487 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530488
Marie Janssendbd48b52016-12-06 09:57:09 -0800489 bt_status_t status =
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700490 sBluetoothHfpClientInterface->connect_audio((const RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800491 if (status != BT_STATUS_SUCCESS) {
492 ALOGE("Failed AG audio connection, status: %d", status);
493 }
494 env->ReleaseByteArrayElements(address, addr, 0);
495 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530496}
497
Marie Janssendbd48b52016-12-06 09:57:09 -0800498static jboolean disconnectAudioNative(JNIEnv* env, jobject object,
499 jbyteArray address) {
500 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530501
Marie Janssendbd48b52016-12-06 09:57:09 -0800502 jbyte* addr = env->GetByteArrayElements(address, NULL);
503 if (!addr) {
504 jniThrowIOException(env, EINVAL);
505 return JNI_FALSE;
506 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530507
Marie Janssendbd48b52016-12-06 09:57:09 -0800508 bt_status_t status =
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700509 sBluetoothHfpClientInterface->disconnect_audio((const RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800510 if (status != BT_STATUS_SUCCESS) {
511 ALOGE("Failed AG audio disconnection, status: %d", status);
512 }
513 env->ReleaseByteArrayElements(address, addr, 0);
514 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530515}
516
Marie Janssendbd48b52016-12-06 09:57:09 -0800517static jboolean startVoiceRecognitionNative(JNIEnv* env, jobject object,
518 jbyteArray address) {
519 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530520
Marie Janssendbd48b52016-12-06 09:57:09 -0800521 jbyte* addr = env->GetByteArrayElements(address, NULL);
522 if (!addr) {
523 jniThrowIOException(env, EINVAL);
524 return JNI_FALSE;
525 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800526
Marie Janssendbd48b52016-12-06 09:57:09 -0800527 bt_status_t status = sBluetoothHfpClientInterface->start_voice_recognition(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700528 (const RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800529 if (status != BT_STATUS_SUCCESS) {
530 ALOGE("Failed to start voice recognition, status: %d", status);
531 }
532 env->ReleaseByteArrayElements(address, addr, 0);
533 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530534}
535
Marie Janssendbd48b52016-12-06 09:57:09 -0800536static jboolean stopVoiceRecognitionNative(JNIEnv* env, jobject object,
537 jbyteArray address) {
538 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530539
Marie Janssendbd48b52016-12-06 09:57:09 -0800540 jbyte* addr = env->GetByteArrayElements(address, NULL);
541 if (!addr) {
542 jniThrowIOException(env, EINVAL);
543 return JNI_FALSE;
544 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800545
Marie Janssendbd48b52016-12-06 09:57:09 -0800546 bt_status_t status = sBluetoothHfpClientInterface->stop_voice_recognition(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700547 (const RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800548 if (status != BT_STATUS_SUCCESS) {
549 ALOGE("Failed to stop voice recognition, status: %d", status);
550 }
551 env->ReleaseByteArrayElements(address, addr, 0);
552 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530553}
554
Marie Janssendbd48b52016-12-06 09:57:09 -0800555static jboolean setVolumeNative(JNIEnv* env, jobject object, jbyteArray address,
556 jint volume_type, jint volume) {
557 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530558
Marie Janssendbd48b52016-12-06 09:57:09 -0800559 jbyte* addr = env->GetByteArrayElements(address, NULL);
560 if (!addr) {
561 jniThrowIOException(env, EINVAL);
562 return JNI_FALSE;
563 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800564
Marie Janssendbd48b52016-12-06 09:57:09 -0800565 bt_status_t status = sBluetoothHfpClientInterface->volume_control(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700566 (const RawAddress*)addr, (bthf_client_volume_type_t)volume_type, volume);
Marie Janssendbd48b52016-12-06 09:57:09 -0800567 if (status != BT_STATUS_SUCCESS) {
568 ALOGE("FAILED to control volume, status: %d", status);
569 }
570 env->ReleaseByteArrayElements(address, addr, 0);
571 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530572}
573
Marie Janssendbd48b52016-12-06 09:57:09 -0800574static jboolean dialNative(JNIEnv* env, jobject object, jbyteArray address,
575 jstring number_str) {
576 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530577
Marie Janssendbd48b52016-12-06 09:57:09 -0800578 jbyte* addr = env->GetByteArrayElements(address, NULL);
579 if (!addr) {
580 jniThrowIOException(env, EINVAL);
581 return JNI_FALSE;
582 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800583
Marie Janssendbd48b52016-12-06 09:57:09 -0800584 const char* number = NULL;
585 if (number_str != NULL) {
586 number = env->GetStringUTFChars(number_str, NULL);
587 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530588
Marie Janssendbd48b52016-12-06 09:57:09 -0800589 bt_status_t status =
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700590 sBluetoothHfpClientInterface->dial((const RawAddress*)addr, number);
Marie Janssendbd48b52016-12-06 09:57:09 -0800591 if (status != BT_STATUS_SUCCESS) {
592 ALOGE("Failed to dial, status: %d", status);
593 }
594 if (number != NULL) {
595 env->ReleaseStringUTFChars(number_str, number);
596 }
597 env->ReleaseByteArrayElements(address, addr, 0);
598 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530599}
600
Marie Janssendbd48b52016-12-06 09:57:09 -0800601static jboolean dialMemoryNative(JNIEnv* env, jobject object,
602 jbyteArray address, jint location) {
603 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530604
Marie Janssendbd48b52016-12-06 09:57:09 -0800605 jbyte* addr = env->GetByteArrayElements(address, NULL);
606 if (!addr) {
607 jniThrowIOException(env, EINVAL);
608 return JNI_FALSE;
609 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800610
Marie Janssendbd48b52016-12-06 09:57:09 -0800611 bt_status_t status = sBluetoothHfpClientInterface->dial_memory(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700612 (const RawAddress*)addr, (int)location);
Marie Janssendbd48b52016-12-06 09:57:09 -0800613 if (status != BT_STATUS_SUCCESS) {
614 ALOGE("Failed to dial from memory, status: %d", status);
615 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800616
Marie Janssendbd48b52016-12-06 09:57:09 -0800617 env->ReleaseByteArrayElements(address, addr, 0);
618 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530619}
620
Marie Janssendbd48b52016-12-06 09:57:09 -0800621static jboolean handleCallActionNative(JNIEnv* env, jobject object,
622 jbyteArray address, jint action,
623 jint index) {
624 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530625
Marie Janssendbd48b52016-12-06 09:57:09 -0800626 jbyte* addr = env->GetByteArrayElements(address, NULL);
627 if (!addr) {
628 jniThrowIOException(env, EINVAL);
629 return JNI_FALSE;
630 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800631
Marie Janssendbd48b52016-12-06 09:57:09 -0800632 bt_status_t status = sBluetoothHfpClientInterface->handle_call_action(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700633 (const RawAddress*)addr, (bthf_client_call_action_t)action, (int)index);
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800634
Marie Janssendbd48b52016-12-06 09:57:09 -0800635 if (status != BT_STATUS_SUCCESS) {
636 ALOGE("Failed to enter private mode, status: %d", status);
637 }
638 env->ReleaseByteArrayElements(address, addr, 0);
639 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530640}
641
Marie Janssendbd48b52016-12-06 09:57:09 -0800642static jboolean queryCurrentCallsNative(JNIEnv* env, jobject object,
643 jbyteArray address) {
644 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530645
Marie Janssendbd48b52016-12-06 09:57:09 -0800646 jbyte* addr = env->GetByteArrayElements(address, NULL);
647 if (!addr) {
648 jniThrowIOException(env, EINVAL);
649 return JNI_FALSE;
650 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800651
Marie Janssendbd48b52016-12-06 09:57:09 -0800652 bt_status_t status = sBluetoothHfpClientInterface->query_current_calls(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700653 (const RawAddress*)addr);
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800654
Marie Janssendbd48b52016-12-06 09:57:09 -0800655 if (status != BT_STATUS_SUCCESS) {
656 ALOGE("Failed to query current calls, status: %d", status);
657 }
658 env->ReleaseByteArrayElements(address, addr, 0);
659 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530660}
661
Marie Janssendbd48b52016-12-06 09:57:09 -0800662static jboolean queryCurrentOperatorNameNative(JNIEnv* env, jobject object,
663 jbyteArray address) {
664 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530665
Marie Janssendbd48b52016-12-06 09:57:09 -0800666 jbyte* addr = env->GetByteArrayElements(address, NULL);
667 if (!addr) {
668 jniThrowIOException(env, EINVAL);
669 return JNI_FALSE;
670 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800671
Marie Janssendbd48b52016-12-06 09:57:09 -0800672 bt_status_t status =
673 sBluetoothHfpClientInterface->query_current_operator_name(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700674 (const RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800675 if (status != BT_STATUS_SUCCESS) {
676 ALOGE("Failed to query current operator name, status: %d", status);
677 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800678
Marie Janssendbd48b52016-12-06 09:57:09 -0800679 env->ReleaseByteArrayElements(address, addr, 0);
680 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530681}
682
Marie Janssendbd48b52016-12-06 09:57:09 -0800683static jboolean retrieveSubscriberInfoNative(JNIEnv* env, jobject object,
684 jbyteArray address) {
685 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530686
Marie Janssendbd48b52016-12-06 09:57:09 -0800687 jbyte* addr = env->GetByteArrayElements(address, NULL);
688 if (!addr) {
689 jniThrowIOException(env, EINVAL);
690 return JNI_FALSE;
691 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800692
Marie Janssendbd48b52016-12-06 09:57:09 -0800693 bt_status_t status = sBluetoothHfpClientInterface->retrieve_subscriber_info(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700694 (const RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800695 if (status != BT_STATUS_SUCCESS) {
696 ALOGE("Failed to retrieve subscriber info, status: %d", status);
697 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800698
Marie Janssendbd48b52016-12-06 09:57:09 -0800699 env->ReleaseByteArrayElements(address, addr, 0);
700 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530701}
702
Joseph Pirozzo39a58902017-04-20 11:30:38 -0700703static jboolean sendDtmfNative(JNIEnv* env, jobject object, jbyteArray address,
704 jbyte code) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800705 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530706
Marie Janssendbd48b52016-12-06 09:57:09 -0800707 jbyte* addr = env->GetByteArrayElements(address, NULL);
708 if (!addr) {
709 jniThrowIOException(env, EINVAL);
710 return JNI_FALSE;
711 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800712
Marie Janssendbd48b52016-12-06 09:57:09 -0800713 bt_status_t status = sBluetoothHfpClientInterface->send_dtmf(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700714 (const RawAddress*)addr, (char)code);
Marie Janssendbd48b52016-12-06 09:57:09 -0800715 if (status != BT_STATUS_SUCCESS) {
716 ALOGE("Failed to send DTMF, status: %d", status);
717 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800718
Marie Janssendbd48b52016-12-06 09:57:09 -0800719 env->ReleaseByteArrayElements(address, addr, 0);
720 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530721}
722
Marie Janssendbd48b52016-12-06 09:57:09 -0800723static jboolean requestLastVoiceTagNumberNative(JNIEnv* env, jobject object,
724 jbyteArray address) {
725 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530726
Marie Janssendbd48b52016-12-06 09:57:09 -0800727 jbyte* addr = env->GetByteArrayElements(address, NULL);
728 if (!addr) {
729 jniThrowIOException(env, EINVAL);
730 return JNI_FALSE;
731 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800732
Marie Janssendbd48b52016-12-06 09:57:09 -0800733 bt_status_t status =
734 sBluetoothHfpClientInterface->request_last_voice_tag_number(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700735 (const RawAddress*)addr);
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800736
Marie Janssendbd48b52016-12-06 09:57:09 -0800737 if (status != BT_STATUS_SUCCESS) {
738 ALOGE("Failed to request last Voice Tag number, status: %d", status);
739 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800740
Marie Janssendbd48b52016-12-06 09:57:09 -0800741 env->ReleaseByteArrayElements(address, addr, 0);
742 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530743}
744
Marie Janssendbd48b52016-12-06 09:57:09 -0800745static jboolean sendATCmdNative(JNIEnv* env, jobject object, jbyteArray address,
746 jint cmd, jint val1, jint val2,
747 jstring arg_str) {
748 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530749
Marie Janssendbd48b52016-12-06 09:57:09 -0800750 jbyte* addr = env->GetByteArrayElements(address, NULL);
751 if (!addr) {
752 jniThrowIOException(env, EINVAL);
753 return JNI_FALSE;
754 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800755
Marie Janssendbd48b52016-12-06 09:57:09 -0800756 const char* arg = NULL;
757 if (arg_str != NULL) {
758 arg = env->GetStringUTFChars(arg_str, NULL);
759 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530760
Marie Janssendbd48b52016-12-06 09:57:09 -0800761 bt_status_t status = sBluetoothHfpClientInterface->send_at_cmd(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700762 (const RawAddress*)addr, cmd, val1, val2, arg);
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800763
Marie Janssendbd48b52016-12-06 09:57:09 -0800764 if (status != BT_STATUS_SUCCESS) {
765 ALOGE("Failed to send cmd, status: %d", status);
766 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530767
Marie Janssendbd48b52016-12-06 09:57:09 -0800768 if (arg != NULL) {
769 env->ReleaseStringUTFChars(arg_str, arg);
770 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800771
Marie Janssendbd48b52016-12-06 09:57:09 -0800772 env->ReleaseByteArrayElements(address, addr, 0);
773 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530774}
775
776static JNINativeMethod sMethods[] = {
Marie Janssendbd48b52016-12-06 09:57:09 -0800777 {"classInitNative", "()V", (void*)classInitNative},
778 {"initializeNative", "()V", (void*)initializeNative},
779 {"cleanupNative", "()V", (void*)cleanupNative},
780 {"connectNative", "([B)Z", (void*)connectNative},
781 {"disconnectNative", "([B)Z", (void*)disconnectNative},
782 {"connectAudioNative", "([B)Z", (void*)connectAudioNative},
783 {"disconnectAudioNative", "([B)Z", (void*)disconnectAudioNative},
784 {"startVoiceRecognitionNative", "([B)Z",
785 (void*)startVoiceRecognitionNative},
786 {"stopVoiceRecognitionNative", "([B)Z", (void*)stopVoiceRecognitionNative},
787 {"setVolumeNative", "([BII)Z", (void*)setVolumeNative},
788 {"dialNative", "([BLjava/lang/String;)Z", (void*)dialNative},
789 {"dialMemoryNative", "([BI)Z", (void*)dialMemoryNative},
790 {"handleCallActionNative", "([BII)Z", (void*)handleCallActionNative},
791 {"queryCurrentCallsNative", "([B)Z", (void*)queryCurrentCallsNative},
792 {"queryCurrentOperatorNameNative", "([B)Z",
793 (void*)queryCurrentOperatorNameNative},
794 {"retrieveSubscriberInfoNative", "([B)Z",
795 (void*)retrieveSubscriberInfoNative},
796 {"sendDtmfNative", "([BB)Z", (void*)sendDtmfNative},
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800797 {"requestLastVoiceTagNumberNative", "([B)Z",
Marie Janssendbd48b52016-12-06 09:57:09 -0800798 (void*)requestLastVoiceTagNumberNative},
799 {"sendATCmdNative", "([BIIILjava/lang/String;)Z", (void*)sendATCmdNative},
Hemant Guptaaebc7262013-08-19 18:54:29 +0530800};
801
Marie Janssendbd48b52016-12-06 09:57:09 -0800802int register_com_android_bluetooth_hfpclient(JNIEnv* env) {
803 return jniRegisterNativeMethods(
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800804 env, "com/android/bluetooth/hfpclient/NativeInterface",
Marie Janssendbd48b52016-12-06 09:57:09 -0800805 sMethods, NELEM(sMethods));
Hemant Guptaaebc7262013-08-19 18:54:29 +0530806}
807
808} /* namespace android */