blob: 83c6b20f36e3c883fb91f727a62c98b42261bbd2 [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
21#include "com_android_bluetooth.h"
22#include "hardware/bt_hf_client.h"
23#include "utils/Log.h"
Hemant Guptaaebc7262013-08-19 18:54:29 +053024
Hemant Guptaaebc7262013-08-19 18:54:29 +053025namespace android {
26
Marie Janssendbd48b52016-12-06 09:57:09 -080027static bthf_client_interface_t* sBluetoothHfpClientInterface = NULL;
Hemant Guptaaebc7262013-08-19 18:54:29 +053028static jobject mCallbacksObj = NULL;
Hemant Guptaaebc7262013-08-19 18:54:29 +053029
30static jmethodID method_onConnectionStateChanged;
31static jmethodID method_onAudioStateChanged;
32static jmethodID method_onVrStateChanged;
33static jmethodID method_onNetworkState;
34static jmethodID method_onNetworkRoaming;
35static jmethodID method_onNetworkSignal;
36static jmethodID method_onBatteryLevel;
37static jmethodID method_onCurrentOperator;
38static jmethodID method_onCall;
39static jmethodID method_onCallSetup;
40static jmethodID method_onCallHeld;
41static jmethodID method_onRespAndHold;
42static jmethodID method_onClip;
43static jmethodID method_onCallWaiting;
44static jmethodID method_onCurrentCalls;
45static jmethodID method_onVolumeChange;
46static jmethodID method_onCmdResult;
47static jmethodID method_onSubscriberInfo;
48static jmethodID method_onInBandRing;
49static jmethodID method_onLastVoiceTagNumber;
50static jmethodID method_onRingIndication;
Deqiang Chen832a2952019-07-01 09:58:47 -070051static jmethodID method_onUnknownEvent;
Hemant Guptaaebc7262013-08-19 18:54:29 +053052
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
weichinweng02683db2019-02-12 18:17:34 +0800158 const char null_str[] = "";
159 if (!sCallbackEnv.isValidUtf(name)) {
160 android_errorWriteLog(0x534e4554, "109838537");
161 ALOGE("%s: name is not a valid UTF string.", __func__);
162 name = null_str;
163 }
164
Marie Janssen479b3482016-10-11 13:54:41 -0700165 ScopedLocalRef<jstring> js_name(sCallbackEnv.get(),
166 sCallbackEnv->NewStringUTF(name));
Marie Janssendbd48b52016-12-06 09:57:09 -0800167 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCurrentOperator,
Marie Janssen479b3482016-10-11 13:54:41 -0700168 js_name.get(), addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530169}
170
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700171static void call_cb(const RawAddress* bd_addr, bthf_client_call_t call) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800172 CallbackEnv sCallbackEnv(__func__);
173 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800174
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000175 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700176 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800177
Marie Janssen479b3482016-10-11 13:54:41 -0700178 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCall, (jint)call,
179 addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530180}
181
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700182static void callsetup_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800183 bthf_client_callsetup_t callsetup) {
184 CallbackEnv sCallbackEnv(__func__);
185 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800186
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000187 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700188 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800189
Marie Janssen19ec7832017-02-22 07:26:34 -0800190 ALOGD("callsetup_cb bdaddr %02x:%02x:%02x:%02x:%02x:%02x",
191 bd_addr->address[0], bd_addr->address[1], bd_addr->address[2],
192 bd_addr->address[3], bd_addr->address[4], bd_addr->address[5]);
Marie Janssen479b3482016-10-11 13:54:41 -0700193
Marie Janssendbd48b52016-12-06 09:57:09 -0800194 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallSetup,
Marie Janssen479b3482016-10-11 13:54:41 -0700195 (jint)callsetup, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530196}
197
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700198static void callheld_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800199 bthf_client_callheld_t callheld) {
200 CallbackEnv sCallbackEnv(__func__);
201 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800202
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000203 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700204 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800205
Marie Janssen479b3482016-10-11 13:54:41 -0700206 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallHeld, (jint)callheld,
207 addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530208}
209
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700210static void resp_and_hold_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800211 bthf_client_resp_and_hold_t resp_and_hold) {
212 CallbackEnv sCallbackEnv(__func__);
213 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800214
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000215 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700216 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800217
Marie Janssendbd48b52016-12-06 09:57:09 -0800218 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRespAndHold,
Marie Janssen479b3482016-10-11 13:54:41 -0700219 (jint)resp_and_hold, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530220}
221
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700222static void clip_cb(const RawAddress* bd_addr, const char* number) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800223 CallbackEnv sCallbackEnv(__func__);
224 if (!sCallbackEnv.valid()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530225
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000226 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700227 if (!addr.get()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800228
weichinweng02683db2019-02-12 18:17:34 +0800229 const char null_str[] = "";
230 if (!sCallbackEnv.isValidUtf(number)) {
231 android_errorWriteLog(0x534e4554, "109838537");
232 ALOGE("%s: number is not a valid UTF string.", __func__);
233 number = null_str;
234 }
235
Marie Janssen479b3482016-10-11 13:54:41 -0700236 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
237 sCallbackEnv->NewStringUTF(number));
238 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClip, js_number.get(),
239 addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530240}
241
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700242static void call_waiting_cb(const RawAddress* bd_addr, const char* number) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800243 CallbackEnv sCallbackEnv(__func__);
244 if (!sCallbackEnv.valid()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530245
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000246 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700247 if (!addr.get()) return;
weichinweng02683db2019-02-12 18:17:34 +0800248
249 const char null_str[] = "";
250 if (!sCallbackEnv.isValidUtf(number)) {
251 android_errorWriteLog(0x534e4554, "109838537");
252 ALOGE("%s: number is not a valid UTF string.", __func__);
253 number = null_str;
254 }
255
Marie Janssen479b3482016-10-11 13:54:41 -0700256 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
257 sCallbackEnv->NewStringUTF(number));
258 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallWaiting,
259 js_number.get(), addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530260}
261
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700262static void current_calls_cb(const RawAddress* bd_addr, int index,
Marie Janssendbd48b52016-12-06 09:57:09 -0800263 bthf_client_call_direction_t dir,
264 bthf_client_call_state_t state,
265 bthf_client_call_mpty_type_t mpty,
266 const char* number) {
267 CallbackEnv sCallbackEnv(__func__);
268 if (!sCallbackEnv.valid()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530269
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000270 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700271 if (!addr.get()) return;
weichinweng02683db2019-02-12 18:17:34 +0800272
273 const char null_str[] = "";
274 if (!sCallbackEnv.isValidUtf(number)) {
275 android_errorWriteLog(0x534e4554, "109838537");
276 ALOGE("%s: number is not a valid UTF string.", __func__);
277 number = null_str;
278 }
279
Marie Janssen479b3482016-10-11 13:54:41 -0700280 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
281 sCallbackEnv->NewStringUTF(number));
Marie Janssendbd48b52016-12-06 09:57:09 -0800282 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCurrentCalls, index, dir,
Marie Janssen479b3482016-10-11 13:54:41 -0700283 state, mpty, js_number.get(), addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530284}
285
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700286static void volume_change_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800287 bthf_client_volume_type_t type, int volume) {
288 CallbackEnv sCallbackEnv(__func__);
289 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800290
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000291 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700292 if (!addr.get()) return;
Marie Janssendbd48b52016-12-06 09:57:09 -0800293 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeChange, (jint)type,
Marie Janssen479b3482016-10-11 13:54:41 -0700294 (jint)volume, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530295}
296
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700297static void cmd_complete_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800298 bthf_client_cmd_complete_t type, int cme) {
299 CallbackEnv sCallbackEnv(__func__);
300 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800301
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000302 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700303 if (!addr.get()) return;
Marie Janssendbd48b52016-12-06 09:57:09 -0800304 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCmdResult, (jint)type,
Marie Janssen479b3482016-10-11 13:54:41 -0700305 (jint)cme, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530306}
307
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700308static void subscriber_info_cb(const RawAddress* bd_addr, const char* name,
Marie Janssendbd48b52016-12-06 09:57:09 -0800309 bthf_client_subscriber_service_type_t type) {
310 CallbackEnv sCallbackEnv(__func__);
311 if (!sCallbackEnv.valid()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530312
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000313 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700314 if (!addr.get()) return;
weichinweng02683db2019-02-12 18:17:34 +0800315
316 const char null_str[] = "";
317 if (!sCallbackEnv.isValidUtf(name)) {
318 android_errorWriteLog(0x534e4554, "109838537");
319 ALOGE("%s: name is not a valid UTF string.", __func__);
320 name = null_str;
321 }
322
Marie Janssen479b3482016-10-11 13:54:41 -0700323 ScopedLocalRef<jstring> js_name(sCallbackEnv.get(),
324 sCallbackEnv->NewStringUTF(name));
325 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSubscriberInfo,
326 js_name.get(), (jint)type, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530327}
328
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700329static void in_band_ring_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800330 bthf_client_in_band_ring_state_t in_band) {
331 CallbackEnv sCallbackEnv(__func__);
332 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800333
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000334 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700335 if (!addr.get()) return;
Marie Janssendbd48b52016-12-06 09:57:09 -0800336 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onInBandRing,
Marie Janssen479b3482016-10-11 13:54:41 -0700337 (jint)in_band, addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530338}
339
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700340static void last_voice_tag_number_cb(const RawAddress* bd_addr,
Marie Janssendbd48b52016-12-06 09:57:09 -0800341 const char* number) {
342 CallbackEnv sCallbackEnv(__func__);
343 if (!sCallbackEnv.valid()) return;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530344
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000345 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700346 if (!addr.get()) return;
weichinweng02683db2019-02-12 18:17:34 +0800347
348 const char null_str[] = "";
349 if (!sCallbackEnv.isValidUtf(number)) {
350 android_errorWriteLog(0x534e4554, "109838537");
351 ALOGE("%s: number is not a valid UTF string.", __func__);
352 number = null_str;
353 }
354
Marie Janssen479b3482016-10-11 13:54:41 -0700355 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
356 sCallbackEnv->NewStringUTF(number));
Marie Janssendbd48b52016-12-06 09:57:09 -0800357 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onLastVoiceTagNumber,
Marie Janssen479b3482016-10-11 13:54:41 -0700358 js_number.get(), addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530359}
360
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700361static void ring_indication_cb(const RawAddress* bd_addr) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800362 CallbackEnv sCallbackEnv(__func__);
363 if (!sCallbackEnv.valid()) return;
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800364
Andre Eisenbach2116dbf2017-03-17 04:47:41 +0000365 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
Marie Janssen479b3482016-10-11 13:54:41 -0700366 if (!addr.get()) return;
367 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRingIndication,
368 addr.get());
Hemant Guptaaebc7262013-08-19 18:54:29 +0530369}
370
Deqiang Chen832a2952019-07-01 09:58:47 -0700371static void unknown_event_cb(const RawAddress* bd_addr,
372 const char* eventString) {
373 CallbackEnv sCallbackEnv(__func__);
374 if (!sCallbackEnv.valid()) return;
375
376 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
377 if (!addr.get()) return;
378
379 ScopedLocalRef<jstring> js_event(sCallbackEnv.get(),
380 sCallbackEnv->NewStringUTF(eventString));
381 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onUnknownEvent,
382 js_event.get(), addr.get());
383}
384
Hemant Guptaaebc7262013-08-19 18:54:29 +0530385static bthf_client_callbacks_t sBluetoothHfpClientCallbacks = {
386 sizeof(sBluetoothHfpClientCallbacks),
387 connection_state_cb,
388 audio_state_cb,
389 vr_cmd_cb,
390 network_state_cb,
391 network_roaming_cb,
392 network_signal_cb,
393 battery_level_cb,
394 current_operator_cb,
395 call_cb,
396 callsetup_cb,
397 callheld_cb,
398 resp_and_hold_cb,
399 clip_cb,
400 call_waiting_cb,
401 current_calls_cb,
402 volume_change_cb,
403 cmd_complete_cb,
404 subscriber_info_cb,
405 in_band_ring_cb,
406 last_voice_tag_number_cb,
407 ring_indication_cb,
Deqiang Chen832a2952019-07-01 09:58:47 -0700408 unknown_event_cb,
Hemant Guptaaebc7262013-08-19 18:54:29 +0530409};
410
411static void classInitNative(JNIEnv* env, jclass clazz) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800412 method_onConnectionStateChanged =
413 env->GetMethodID(clazz, "onConnectionStateChanged", "(III[B)V");
414 method_onAudioStateChanged =
415 env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V");
Joseph Pirozzoa4cca002017-10-06 14:04:22 -0700416 method_onVrStateChanged =
417 env->GetMethodID(clazz, "onVrStateChanged", "(I[B)V");
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800418 method_onNetworkState = env->GetMethodID(clazz, "onNetworkState", "(I[B)V");
419 method_onNetworkRoaming = env->GetMethodID(clazz, "onNetworkRoaming", "(I[B)V");
420 method_onNetworkSignal = env->GetMethodID(clazz, "onNetworkSignal", "(I[B)V");
421 method_onBatteryLevel = env->GetMethodID(clazz, "onBatteryLevel", "(I[B)V");
Marie Janssendbd48b52016-12-06 09:57:09 -0800422 method_onCurrentOperator =
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800423 env->GetMethodID(clazz, "onCurrentOperator", "(Ljava/lang/String;[B)V");
424 method_onCall = env->GetMethodID(clazz, "onCall", "(I[B)V");
425 method_onCallSetup = env->GetMethodID(clazz, "onCallSetup", "(I[B)V");
426 method_onCallHeld = env->GetMethodID(clazz, "onCallHeld", "(I[B)V");
427 method_onRespAndHold = env->GetMethodID(clazz, "onRespAndHold", "(I[B)V");
428 method_onClip = env->GetMethodID(clazz, "onClip", "(Ljava/lang/String;[B)V");
Marie Janssendbd48b52016-12-06 09:57:09 -0800429 method_onCallWaiting =
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800430 env->GetMethodID(clazz, "onCallWaiting", "(Ljava/lang/String;[B)V");
Marie Janssendbd48b52016-12-06 09:57:09 -0800431 method_onCurrentCalls =
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800432 env->GetMethodID(clazz, "onCurrentCalls", "(IIIILjava/lang/String;[B)V");
433 method_onVolumeChange = env->GetMethodID(clazz, "onVolumeChange", "(II[B)V");
434 method_onCmdResult = env->GetMethodID(clazz, "onCmdResult", "(II[B)V");
Marie Janssendbd48b52016-12-06 09:57:09 -0800435 method_onSubscriberInfo =
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800436 env->GetMethodID(clazz, "onSubscriberInfo", "(Ljava/lang/String;I[B)V");
437 method_onInBandRing = env->GetMethodID(clazz, "onInBandRing", "(I[B)V");
Marie Janssendbd48b52016-12-06 09:57:09 -0800438 method_onLastVoiceTagNumber =
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800439 env->GetMethodID(clazz, "onLastVoiceTagNumber", "(Ljava/lang/String;[B)V");
440 method_onRingIndication = env->GetMethodID(clazz, "onRingIndication", "([B)V");
Deqiang Chen832a2952019-07-01 09:58:47 -0700441 method_onUnknownEvent =
442 env->GetMethodID(clazz, "onUnknownEvent", "(Ljava/lang/String;[B)V");
Hemant Guptaaebc7262013-08-19 18:54:29 +0530443
Marie Janssendbd48b52016-12-06 09:57:09 -0800444 ALOGI("%s succeeds", __func__);
Hemant Guptaaebc7262013-08-19 18:54:29 +0530445}
446
Marie Janssendbd48b52016-12-06 09:57:09 -0800447static void initializeNative(JNIEnv* env, jobject object) {
Sanket Agarwal727dc792017-01-24 14:59:31 -0800448 ALOGD("%s: HfpClient", __func__);
Marie Janssendbd48b52016-12-06 09:57:09 -0800449 const bt_interface_t* btInf = getBluetoothInterface();
450 if (btInf == NULL) {
451 ALOGE("Bluetooth module is not loaded");
452 return;
453 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530454
Marie Janssendbd48b52016-12-06 09:57:09 -0800455 if (sBluetoothHfpClientInterface != NULL) {
456 ALOGW("Cleaning up Bluetooth HFP Client Interface before initializing");
457 sBluetoothHfpClientInterface->cleanup();
458 sBluetoothHfpClientInterface = NULL;
459 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530460
Marie Janssendbd48b52016-12-06 09:57:09 -0800461 if (mCallbacksObj != NULL) {
462 ALOGW("Cleaning up Bluetooth HFP Client callback object");
463 env->DeleteGlobalRef(mCallbacksObj);
464 mCallbacksObj = NULL;
465 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530466
Marie Janssendbd48b52016-12-06 09:57:09 -0800467 sBluetoothHfpClientInterface =
468 (bthf_client_interface_t*)btInf->get_profile_interface(
469 BT_PROFILE_HANDSFREE_CLIENT_ID);
470 if (sBluetoothHfpClientInterface == NULL) {
471 ALOGE("Failed to get Bluetooth HFP Client Interface");
472 return;
473 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530474
Marie Janssendbd48b52016-12-06 09:57:09 -0800475 bt_status_t status =
476 sBluetoothHfpClientInterface->init(&sBluetoothHfpClientCallbacks);
477 if (status != BT_STATUS_SUCCESS) {
478 ALOGE("Failed to initialize Bluetooth HFP Client, status: %d", status);
479 sBluetoothHfpClientInterface = NULL;
480 return;
481 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530482
Marie Janssendbd48b52016-12-06 09:57:09 -0800483 mCallbacksObj = env->NewGlobalRef(object);
Hemant Guptaaebc7262013-08-19 18:54:29 +0530484}
485
Marie Janssendbd48b52016-12-06 09:57:09 -0800486static void cleanupNative(JNIEnv* env, jobject object) {
487 const bt_interface_t* btInf = getBluetoothInterface();
488 if (btInf == NULL) {
489 ALOGE("Bluetooth module is not loaded");
490 return;
491 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530492
Marie Janssendbd48b52016-12-06 09:57:09 -0800493 if (sBluetoothHfpClientInterface != NULL) {
494 ALOGW("Cleaning up Bluetooth HFP Client Interface...");
495 sBluetoothHfpClientInterface->cleanup();
496 sBluetoothHfpClientInterface = NULL;
497 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530498
Marie Janssendbd48b52016-12-06 09:57:09 -0800499 if (mCallbacksObj != NULL) {
500 ALOGW("Cleaning up Bluetooth HFP Client callback object");
501 env->DeleteGlobalRef(mCallbacksObj);
502 mCallbacksObj = NULL;
503 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530504}
505
Marie Janssendbd48b52016-12-06 09:57:09 -0800506static jboolean connectNative(JNIEnv* env, jobject object, jbyteArray address) {
507 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530508
Marie Janssendbd48b52016-12-06 09:57:09 -0800509 jbyte* addr = env->GetByteArrayElements(address, NULL);
510 if (!addr) {
511 jniThrowIOException(env, EINVAL);
512 return JNI_FALSE;
513 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530514
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700515 bt_status_t status = sBluetoothHfpClientInterface->connect((RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800516 if (status != BT_STATUS_SUCCESS) {
517 ALOGE("Failed AG connection, status: %d", status);
518 }
519 env->ReleaseByteArrayElements(address, addr, 0);
520 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530521}
522
Marie Janssendbd48b52016-12-06 09:57:09 -0800523static jboolean disconnectNative(JNIEnv* env, jobject object,
524 jbyteArray address) {
525 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530526
Marie Janssendbd48b52016-12-06 09:57:09 -0800527 jbyte* addr = env->GetByteArrayElements(address, NULL);
528 if (!addr) {
529 jniThrowIOException(env, EINVAL);
530 return JNI_FALSE;
531 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530532
Marie Janssendbd48b52016-12-06 09:57:09 -0800533 bt_status_t status =
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700534 sBluetoothHfpClientInterface->disconnect((const RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800535 if (status != BT_STATUS_SUCCESS) {
536 ALOGE("Failed AG disconnection, status: %d", status);
537 }
538 env->ReleaseByteArrayElements(address, addr, 0);
539 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530540}
541
Marie Janssendbd48b52016-12-06 09:57:09 -0800542static jboolean connectAudioNative(JNIEnv* env, jobject object,
543 jbyteArray address) {
544 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530545
Marie Janssendbd48b52016-12-06 09:57:09 -0800546 jbyte* addr = env->GetByteArrayElements(address, NULL);
547 if (!addr) {
548 jniThrowIOException(env, EINVAL);
549 return JNI_FALSE;
550 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530551
Marie Janssendbd48b52016-12-06 09:57:09 -0800552 bt_status_t status =
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700553 sBluetoothHfpClientInterface->connect_audio((const RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800554 if (status != BT_STATUS_SUCCESS) {
555 ALOGE("Failed AG audio connection, status: %d", status);
556 }
557 env->ReleaseByteArrayElements(address, addr, 0);
558 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530559}
560
Marie Janssendbd48b52016-12-06 09:57:09 -0800561static jboolean disconnectAudioNative(JNIEnv* env, jobject object,
562 jbyteArray address) {
563 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530564
Marie Janssendbd48b52016-12-06 09:57:09 -0800565 jbyte* addr = env->GetByteArrayElements(address, NULL);
566 if (!addr) {
567 jniThrowIOException(env, EINVAL);
568 return JNI_FALSE;
569 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530570
Marie Janssendbd48b52016-12-06 09:57:09 -0800571 bt_status_t status =
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700572 sBluetoothHfpClientInterface->disconnect_audio((const RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800573 if (status != BT_STATUS_SUCCESS) {
574 ALOGE("Failed AG audio disconnection, status: %d", status);
575 }
576 env->ReleaseByteArrayElements(address, addr, 0);
577 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530578}
579
Marie Janssendbd48b52016-12-06 09:57:09 -0800580static jboolean startVoiceRecognitionNative(JNIEnv* env, jobject object,
581 jbyteArray address) {
582 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530583
Marie Janssendbd48b52016-12-06 09:57:09 -0800584 jbyte* addr = env->GetByteArrayElements(address, NULL);
585 if (!addr) {
586 jniThrowIOException(env, EINVAL);
587 return JNI_FALSE;
588 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800589
Marie Janssendbd48b52016-12-06 09:57:09 -0800590 bt_status_t status = sBluetoothHfpClientInterface->start_voice_recognition(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700591 (const RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800592 if (status != BT_STATUS_SUCCESS) {
593 ALOGE("Failed to start voice recognition, status: %d", status);
594 }
595 env->ReleaseByteArrayElements(address, addr, 0);
596 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530597}
598
Marie Janssendbd48b52016-12-06 09:57:09 -0800599static jboolean stopVoiceRecognitionNative(JNIEnv* env, jobject object,
600 jbyteArray address) {
601 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530602
Marie Janssendbd48b52016-12-06 09:57:09 -0800603 jbyte* addr = env->GetByteArrayElements(address, NULL);
604 if (!addr) {
605 jniThrowIOException(env, EINVAL);
606 return JNI_FALSE;
607 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800608
Marie Janssendbd48b52016-12-06 09:57:09 -0800609 bt_status_t status = sBluetoothHfpClientInterface->stop_voice_recognition(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700610 (const RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800611 if (status != BT_STATUS_SUCCESS) {
612 ALOGE("Failed to stop voice recognition, status: %d", status);
613 }
614 env->ReleaseByteArrayElements(address, addr, 0);
615 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530616}
617
Marie Janssendbd48b52016-12-06 09:57:09 -0800618static jboolean setVolumeNative(JNIEnv* env, jobject object, jbyteArray address,
619 jint volume_type, jint volume) {
620 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530621
Marie Janssendbd48b52016-12-06 09:57:09 -0800622 jbyte* addr = env->GetByteArrayElements(address, NULL);
623 if (!addr) {
624 jniThrowIOException(env, EINVAL);
625 return JNI_FALSE;
626 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800627
Marie Janssendbd48b52016-12-06 09:57:09 -0800628 bt_status_t status = sBluetoothHfpClientInterface->volume_control(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700629 (const RawAddress*)addr, (bthf_client_volume_type_t)volume_type, volume);
Marie Janssendbd48b52016-12-06 09:57:09 -0800630 if (status != BT_STATUS_SUCCESS) {
631 ALOGE("FAILED to control volume, status: %d", status);
632 }
633 env->ReleaseByteArrayElements(address, addr, 0);
634 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530635}
636
Marie Janssendbd48b52016-12-06 09:57:09 -0800637static jboolean dialNative(JNIEnv* env, jobject object, jbyteArray address,
638 jstring number_str) {
639 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530640
Marie Janssendbd48b52016-12-06 09:57:09 -0800641 jbyte* addr = env->GetByteArrayElements(address, NULL);
642 if (!addr) {
643 jniThrowIOException(env, EINVAL);
644 return JNI_FALSE;
645 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800646
Satish Kodishalaea517762016-02-11 15:00:13 +0530647 const char* number = nullptr;
648 if (number_str != nullptr) {
649 number = env->GetStringUTFChars(number_str, nullptr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800650 }
Marie Janssendbd48b52016-12-06 09:57:09 -0800651 bt_status_t status =
Satish Kodishalaea517762016-02-11 15:00:13 +0530652 sBluetoothHfpClientInterface->dial((const RawAddress*)addr,
653 number == nullptr ? "" : number);
654
Marie Janssendbd48b52016-12-06 09:57:09 -0800655 if (status != BT_STATUS_SUCCESS) {
656 ALOGE("Failed to dial, status: %d", status);
657 }
Satish Kodishalaea517762016-02-11 15:00:13 +0530658 if (number != nullptr) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800659 env->ReleaseStringUTFChars(number_str, number);
660 }
661 env->ReleaseByteArrayElements(address, addr, 0);
662 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530663}
664
Marie Janssendbd48b52016-12-06 09:57:09 -0800665static jboolean dialMemoryNative(JNIEnv* env, jobject object,
666 jbyteArray address, jint location) {
667 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530668
Marie Janssendbd48b52016-12-06 09:57:09 -0800669 jbyte* addr = env->GetByteArrayElements(address, NULL);
670 if (!addr) {
671 jniThrowIOException(env, EINVAL);
672 return JNI_FALSE;
673 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800674
Marie Janssendbd48b52016-12-06 09:57:09 -0800675 bt_status_t status = sBluetoothHfpClientInterface->dial_memory(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700676 (const RawAddress*)addr, (int)location);
Marie Janssendbd48b52016-12-06 09:57:09 -0800677 if (status != BT_STATUS_SUCCESS) {
678 ALOGE("Failed to dial from memory, status: %d", status);
679 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800680
Marie Janssendbd48b52016-12-06 09:57:09 -0800681 env->ReleaseByteArrayElements(address, addr, 0);
682 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530683}
684
Marie Janssendbd48b52016-12-06 09:57:09 -0800685static jboolean handleCallActionNative(JNIEnv* env, jobject object,
686 jbyteArray address, jint action,
687 jint index) {
688 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530689
Marie Janssendbd48b52016-12-06 09:57:09 -0800690 jbyte* addr = env->GetByteArrayElements(address, NULL);
691 if (!addr) {
692 jniThrowIOException(env, EINVAL);
693 return JNI_FALSE;
694 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800695
Marie Janssendbd48b52016-12-06 09:57:09 -0800696 bt_status_t status = sBluetoothHfpClientInterface->handle_call_action(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700697 (const RawAddress*)addr, (bthf_client_call_action_t)action, (int)index);
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800698
Marie Janssendbd48b52016-12-06 09:57:09 -0800699 if (status != BT_STATUS_SUCCESS) {
700 ALOGE("Failed to enter private mode, status: %d", status);
701 }
702 env->ReleaseByteArrayElements(address, addr, 0);
703 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530704}
705
Marie Janssendbd48b52016-12-06 09:57:09 -0800706static jboolean queryCurrentCallsNative(JNIEnv* env, jobject object,
707 jbyteArray address) {
708 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530709
Marie Janssendbd48b52016-12-06 09:57:09 -0800710 jbyte* addr = env->GetByteArrayElements(address, NULL);
711 if (!addr) {
712 jniThrowIOException(env, EINVAL);
713 return JNI_FALSE;
714 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800715
Marie Janssendbd48b52016-12-06 09:57:09 -0800716 bt_status_t status = sBluetoothHfpClientInterface->query_current_calls(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700717 (const RawAddress*)addr);
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800718
Marie Janssendbd48b52016-12-06 09:57:09 -0800719 if (status != BT_STATUS_SUCCESS) {
720 ALOGE("Failed to query current calls, status: %d", status);
721 }
722 env->ReleaseByteArrayElements(address, addr, 0);
723 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530724}
725
Marie Janssendbd48b52016-12-06 09:57:09 -0800726static jboolean queryCurrentOperatorNameNative(JNIEnv* env, jobject object,
727 jbyteArray address) {
728 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530729
Marie Janssendbd48b52016-12-06 09:57:09 -0800730 jbyte* addr = env->GetByteArrayElements(address, NULL);
731 if (!addr) {
732 jniThrowIOException(env, EINVAL);
733 return JNI_FALSE;
734 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800735
Marie Janssendbd48b52016-12-06 09:57:09 -0800736 bt_status_t status =
737 sBluetoothHfpClientInterface->query_current_operator_name(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700738 (const RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800739 if (status != BT_STATUS_SUCCESS) {
740 ALOGE("Failed to query current operator name, status: %d", status);
741 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800742
Marie Janssendbd48b52016-12-06 09:57:09 -0800743 env->ReleaseByteArrayElements(address, addr, 0);
744 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530745}
746
Marie Janssendbd48b52016-12-06 09:57:09 -0800747static jboolean retrieveSubscriberInfoNative(JNIEnv* env, jobject object,
748 jbyteArray address) {
749 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530750
Marie Janssendbd48b52016-12-06 09:57:09 -0800751 jbyte* addr = env->GetByteArrayElements(address, NULL);
752 if (!addr) {
753 jniThrowIOException(env, EINVAL);
754 return JNI_FALSE;
755 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800756
Marie Janssendbd48b52016-12-06 09:57:09 -0800757 bt_status_t status = sBluetoothHfpClientInterface->retrieve_subscriber_info(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700758 (const RawAddress*)addr);
Marie Janssendbd48b52016-12-06 09:57:09 -0800759 if (status != BT_STATUS_SUCCESS) {
760 ALOGE("Failed to retrieve subscriber info, status: %d", status);
761 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800762
Marie Janssendbd48b52016-12-06 09:57:09 -0800763 env->ReleaseByteArrayElements(address, addr, 0);
764 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530765}
766
Joseph Pirozzo39a58902017-04-20 11:30:38 -0700767static jboolean sendDtmfNative(JNIEnv* env, jobject object, jbyteArray address,
768 jbyte code) {
Marie Janssendbd48b52016-12-06 09:57:09 -0800769 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530770
Marie Janssendbd48b52016-12-06 09:57:09 -0800771 jbyte* addr = env->GetByteArrayElements(address, NULL);
772 if (!addr) {
773 jniThrowIOException(env, EINVAL);
774 return JNI_FALSE;
775 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800776
Marie Janssendbd48b52016-12-06 09:57:09 -0800777 bt_status_t status = sBluetoothHfpClientInterface->send_dtmf(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700778 (const RawAddress*)addr, (char)code);
Marie Janssendbd48b52016-12-06 09:57:09 -0800779 if (status != BT_STATUS_SUCCESS) {
780 ALOGE("Failed to send DTMF, status: %d", status);
781 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800782
Marie Janssendbd48b52016-12-06 09:57:09 -0800783 env->ReleaseByteArrayElements(address, addr, 0);
784 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530785}
786
Marie Janssendbd48b52016-12-06 09:57:09 -0800787static jboolean requestLastVoiceTagNumberNative(JNIEnv* env, jobject object,
788 jbyteArray address) {
789 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530790
Marie Janssendbd48b52016-12-06 09:57:09 -0800791 jbyte* addr = env->GetByteArrayElements(address, NULL);
792 if (!addr) {
793 jniThrowIOException(env, EINVAL);
794 return JNI_FALSE;
795 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800796
Marie Janssendbd48b52016-12-06 09:57:09 -0800797 bt_status_t status =
798 sBluetoothHfpClientInterface->request_last_voice_tag_number(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700799 (const RawAddress*)addr);
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800800
Marie Janssendbd48b52016-12-06 09:57:09 -0800801 if (status != BT_STATUS_SUCCESS) {
802 ALOGE("Failed to request last Voice Tag number, status: %d", status);
803 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800804
Marie Janssendbd48b52016-12-06 09:57:09 -0800805 env->ReleaseByteArrayElements(address, addr, 0);
806 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530807}
808
Marie Janssendbd48b52016-12-06 09:57:09 -0800809static jboolean sendATCmdNative(JNIEnv* env, jobject object, jbyteArray address,
810 jint cmd, jint val1, jint val2,
811 jstring arg_str) {
812 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530813
Marie Janssendbd48b52016-12-06 09:57:09 -0800814 jbyte* addr = env->GetByteArrayElements(address, NULL);
815 if (!addr) {
816 jniThrowIOException(env, EINVAL);
817 return JNI_FALSE;
818 }
Marie Janssendbd48b52016-12-06 09:57:09 -0800819 const char* arg = NULL;
820 if (arg_str != NULL) {
821 arg = env->GetStringUTFChars(arg_str, NULL);
822 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530823
Marie Janssendbd48b52016-12-06 09:57:09 -0800824 bt_status_t status = sBluetoothHfpClientInterface->send_at_cmd(
Jakub Pawlowskicb399252017-06-24 17:27:01 -0700825 (const RawAddress*)addr, cmd, val1, val2, arg);
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800826
Marie Janssendbd48b52016-12-06 09:57:09 -0800827 if (status != BT_STATUS_SUCCESS) {
828 ALOGE("Failed to send cmd, status: %d", status);
829 }
Hemant Guptaaebc7262013-08-19 18:54:29 +0530830
Marie Janssendbd48b52016-12-06 09:57:09 -0800831 if (arg != NULL) {
832 env->ReleaseStringUTFChars(arg_str, arg);
833 }
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800834
Marie Janssendbd48b52016-12-06 09:57:09 -0800835 env->ReleaseByteArrayElements(address, addr, 0);
836 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
Hemant Guptaaebc7262013-08-19 18:54:29 +0530837}
838
839static JNINativeMethod sMethods[] = {
Marie Janssendbd48b52016-12-06 09:57:09 -0800840 {"classInitNative", "()V", (void*)classInitNative},
841 {"initializeNative", "()V", (void*)initializeNative},
842 {"cleanupNative", "()V", (void*)cleanupNative},
843 {"connectNative", "([B)Z", (void*)connectNative},
844 {"disconnectNative", "([B)Z", (void*)disconnectNative},
845 {"connectAudioNative", "([B)Z", (void*)connectAudioNative},
846 {"disconnectAudioNative", "([B)Z", (void*)disconnectAudioNative},
847 {"startVoiceRecognitionNative", "([B)Z",
848 (void*)startVoiceRecognitionNative},
849 {"stopVoiceRecognitionNative", "([B)Z", (void*)stopVoiceRecognitionNative},
850 {"setVolumeNative", "([BII)Z", (void*)setVolumeNative},
851 {"dialNative", "([BLjava/lang/String;)Z", (void*)dialNative},
852 {"dialMemoryNative", "([BI)Z", (void*)dialMemoryNative},
853 {"handleCallActionNative", "([BII)Z", (void*)handleCallActionNative},
854 {"queryCurrentCallsNative", "([B)Z", (void*)queryCurrentCallsNative},
855 {"queryCurrentOperatorNameNative", "([B)Z",
856 (void*)queryCurrentOperatorNameNative},
857 {"retrieveSubscriberInfoNative", "([B)Z",
858 (void*)retrieveSubscriberInfoNative},
859 {"sendDtmfNative", "([BB)Z", (void*)sendDtmfNative},
Sanket Agarwalef3a3b52016-11-28 15:53:06 -0800860 {"requestLastVoiceTagNumberNative", "([B)Z",
Marie Janssendbd48b52016-12-06 09:57:09 -0800861 (void*)requestLastVoiceTagNumberNative},
862 {"sendATCmdNative", "([BIIILjava/lang/String;)Z", (void*)sendATCmdNative},
Hemant Guptaaebc7262013-08-19 18:54:29 +0530863};
864
Marie Janssendbd48b52016-12-06 09:57:09 -0800865int register_com_android_bluetooth_hfpclient(JNIEnv* env) {
866 return jniRegisterNativeMethods(
Sanket Agarwal84f977c2016-12-14 14:09:38 -0800867 env, "com/android/bluetooth/hfpclient/NativeInterface",
Marie Janssendbd48b52016-12-06 09:57:09 -0800868 sMethods, NELEM(sMethods));
Hemant Guptaaebc7262013-08-19 18:54:29 +0530869}
870
871} /* namespace android */