NativeInterface.java revision c4fbd756e2645147470c486ae96f2253f5e13a52
1/* 2 * Copyright (c) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* 18 * Defines the native inteface that is used by state machine/service to either or receive messages 19 * from the native stack. This file is registered for the native methods in corresponding CPP file. 20 */ 21package com.android.bluetooth.hfpclient; 22 23import android.bluetooth.BluetoothAdapter; 24import android.bluetooth.BluetoothDevice; 25import android.util.Log; 26 27class NativeInterface { 28 private static final String TAG = "NativeInterface"; 29 private static final boolean DBG = false; 30 31 NativeInterface() {} 32 33 // Native methods that call into the JNI interface 34 static native void classInitNative(); 35 36 static native void initializeNative(); 37 38 static native void cleanupNative(); 39 40 static native boolean connectNative(byte[] address); 41 42 static native boolean disconnectNative(byte[] address); 43 44 static native boolean connectAudioNative(byte[] address); 45 46 static native boolean disconnectAudioNative(byte[] address); 47 48 static native boolean startVoiceRecognitionNative(byte[] address); 49 50 static native boolean stopVoiceRecognitionNative(byte[] address); 51 52 static native boolean setVolumeNative(byte[] address, int volumeType, int volume); 53 54 static native boolean dialNative(byte[] address, String number); 55 56 static native boolean dialMemoryNative(byte[] address, int location); 57 58 static native boolean handleCallActionNative(byte[] address, int action, int index); 59 60 static native boolean queryCurrentCallsNative(byte[] address); 61 62 static native boolean queryCurrentOperatorNameNative(byte[] address); 63 64 static native boolean retrieveSubscriberInfoNative(byte[] address); 65 66 static native boolean sendDtmfNative(byte[] address, byte code); 67 68 static native boolean requestLastVoiceTagNumberNative(byte[] address); 69 70 static native boolean sendATCmdNative(byte[] address, int atCmd, int val1, int val2, 71 String arg); 72 73 private BluetoothDevice getDevice(byte[] address) { 74 return BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); 75 } 76 77 // Callbacks from the native back into the java framework. All callbacks are routed via the 78 // Service which will disambiguate which state machine the message should be routed through. 79 private void onConnectionStateChanged(int state, int peerFeat, int chldFeat, byte[] address) { 80 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 81 event.valueInt = state; 82 event.valueInt2 = peerFeat; 83 event.valueInt3 = chldFeat; 84 event.device = getDevice(address); 85 // BluetoothAdapter.getDefaultAdapter().getRemoteDevice(Utils.getAddressStringFromByte 86 // (address)); 87 if (DBG) { 88 Log.d(TAG, "Device addr " + event.device.getAddress() + " State " + state); 89 } 90 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 91 if (service != null) { 92 service.messageFromNative(event); 93 } else { 94 Log.w(TAG, "Ignoring message because service not available: " + event); 95 } 96 } 97 98 private void onAudioStateChanged(int state, byte[] address) { 99 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED); 100 event.valueInt = state; 101 event.device = getDevice(address); 102 if (DBG) { 103 Log.d(TAG, "onAudioStateChanged: address " + address + " event " + event); 104 } 105 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 106 if (service != null) { 107 service.messageFromNative(event); 108 } else { 109 Log.w(TAG, "onAudioStateChanged: Ignoring message because service not available: " 110 + event); 111 } 112 } 113 114 private void onVrStateChanged(int state) { 115 Log.w(TAG, "onVrStateChanged not supported"); 116 } 117 118 private void onNetworkState(int state, byte[] address) { 119 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_NETWORK_STATE); 120 event.valueInt = state; 121 event.device = getDevice(address); 122 if (DBG) { 123 Log.d(TAG, "onVrStateChanged: address " + address + " event " + event); 124 } 125 126 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 127 if (service != null) { 128 service.messageFromNative(event); 129 } else { 130 Log.w(TAG, 131 "onVrStateChanged: Ignoring message because service not available: " + event); 132 } 133 } 134 135 private void onNetworkRoaming(int state, byte[] address) { 136 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_ROAMING_STATE); 137 event.valueInt = state; 138 event.device = getDevice(address); 139 if (DBG) { 140 Log.d(TAG, "onNetworkRoaming: incoming: " + event); 141 } 142 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 143 if (service != null) { 144 service.messageFromNative(event); 145 } else { 146 Log.w(TAG, 147 "onNetworkRoaming: Ignoring message because service not available: " + event); 148 } 149 } 150 151 private void onNetworkSignal(int signal, byte[] address) { 152 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_NETWORK_SIGNAL); 153 event.valueInt = signal; 154 event.device = getDevice(address); 155 if (DBG) { 156 Log.d(TAG, "onNetworkSignal: address " + address + " event " + event); 157 } 158 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 159 if (service != null) { 160 service.messageFromNative(event); 161 } else { 162 Log.w(TAG, "onNetworkSignal: Ignoring message because service not available: " + event); 163 } 164 } 165 166 private void onBatteryLevel(int level, byte[] address) { 167 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_BATTERY_LEVEL); 168 event.valueInt = level; 169 event.device = getDevice(address); 170 if (DBG) { 171 Log.d(TAG, "onBatteryLevel: address " + address + " event " + event); 172 } 173 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 174 if (service != null) { 175 service.messageFromNative(event); 176 } else { 177 Log.w(TAG, "onBatteryLevel: Ignoring message because service not available: " + event); 178 } 179 } 180 181 private void onCurrentOperator(String name, byte[] address) { 182 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_OPERATOR_NAME); 183 event.valueString = name; 184 event.device = getDevice(address); 185 if (DBG) { 186 Log.d(TAG, "onCurrentOperator: address " + address + " event " + event); 187 } 188 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 189 if (service != null) { 190 service.messageFromNative(event); 191 } else { 192 Log.w(TAG, 193 "onCurrentOperator: Ignoring message because service not available: " + event); 194 } 195 } 196 197 private void onCall(int call, byte[] address) { 198 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALL); 199 event.valueInt = call; 200 event.device = getDevice(address); 201 if (DBG) { 202 Log.d(TAG, "onCall: address " + address + " event " + event); 203 } 204 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 205 if (service != null) { 206 service.messageFromNative(event); 207 } else { 208 Log.w(TAG, "onCall: Ignoring message because service not available: " + event); 209 } 210 } 211 212 /** 213 * CIEV (Call indicators) notifying if call(s) are getting set up. 214 * 215 * Values include: 216 * 0 - No current call is in setup 217 * 1 - Incoming call process ongoing 218 * 2 - Outgoing call process ongoing 219 * 3 - Remote party being alerted for outgoing call 220 */ 221 private void onCallSetup(int callsetup, byte[] address) { 222 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALLSETUP); 223 event.valueInt = callsetup; 224 event.device = getDevice(address); 225 if (DBG) { 226 Log.d(TAG, "onCallSetup: addr " + address + " device" + event.device); 227 Log.d(TAG, "onCallSetup: address " + address + " event " + event); 228 } 229 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 230 if (service != null) { 231 service.messageFromNative(event); 232 } else { 233 Log.w(TAG, "onCallSetup: Ignoring message because service not available: " + event); 234 } 235 } 236 237 /** 238 * CIEV (Call indicators) notifying call held states. 239 * 240 * Values include: 241 * 0 - No calls held 242 * 1 - Call is placed on hold or active/held calls wapped (The AG has both an ACTIVE and HELD 243 * call) 244 * 2 - Call on hold, no active call 245 */ 246 private void onCallHeld(int callheld, byte[] address) { 247 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALLHELD); 248 event.valueInt = callheld; 249 event.device = getDevice(address); 250 if (DBG) { 251 Log.d(TAG, "onCallHeld: address " + address + " event " + event); 252 } 253 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 254 if (service != null) { 255 service.messageFromNative(event); 256 } else { 257 Log.w(TAG, "onCallHeld: Ignoring message because service not available: " + event); 258 } 259 } 260 261 private void onRespAndHold(int respAndHold, byte[] address) { 262 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_RESP_AND_HOLD); 263 event.valueInt = respAndHold; 264 event.device = getDevice(address); 265 if (DBG) { 266 Log.d(TAG, "onRespAndHold: address " + address + " event " + event); 267 } 268 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 269 if (service != null) { 270 service.messageFromNative(event); 271 } else { 272 Log.w(TAG, "onRespAndHold: Ignoring message because service not available: " + event); 273 } 274 } 275 276 private void onClip(String number, byte[] address) { 277 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CLIP); 278 event.valueString = number; 279 event.device = getDevice(address); 280 if (DBG) { 281 Log.d(TAG, "onClip: address " + address + " event " + event); 282 } 283 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 284 if (service != null) { 285 service.messageFromNative(event); 286 } else { 287 Log.w(TAG, "onClip: Ignoring message because service not available: " + event); 288 } 289 } 290 291 private void onCallWaiting(String number, byte[] address) { 292 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALL_WAITING); 293 event.valueString = number; 294 event.device = getDevice(address); 295 if (DBG) { 296 Log.d(TAG, "onCallWaiting: address " + address + " event " + event); 297 } 298 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 299 if (service != null) { 300 service.messageFromNative(event); 301 } else { 302 Log.w(TAG, "onCallWaiting: Ignoring message because service not available: " + event); 303 } 304 } 305 306 private void onCurrentCalls(int index, int dir, int state, int mparty, String number, 307 byte[] address) { 308 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CURRENT_CALLS); 309 event.valueInt = index; 310 event.valueInt2 = dir; 311 event.valueInt3 = state; 312 event.valueInt4 = mparty; 313 event.valueString = number; 314 event.device = getDevice(address); 315 if (DBG) { 316 Log.d(TAG, "onCurrentCalls: address " + address + " event " + event); 317 } 318 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 319 if (service != null) { 320 service.messageFromNative(event); 321 } else { 322 Log.w(TAG, "onCurrentCalls: Ignoring message because service not available: " + event); 323 } 324 } 325 326 private void onVolumeChange(int type, int volume, byte[] address) { 327 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_VOLUME_CHANGED); 328 event.valueInt = type; 329 event.valueInt2 = volume; 330 event.device = getDevice(address); 331 if (DBG) { 332 Log.d(TAG, "onVolumeChange: address " + address + " event " + event); 333 } 334 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 335 if (service != null) { 336 service.messageFromNative(event); 337 } else { 338 Log.w(TAG, "onVolumeChange: Ignoring message because service not available: " + event); 339 } 340 } 341 342 private void onCmdResult(int type, int cme, byte[] address) { 343 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT); 344 event.valueInt = type; 345 event.valueInt2 = cme; 346 event.device = getDevice(address); 347 if (DBG) { 348 Log.d(TAG, "onCmdResult: address " + address + " event " + event); 349 } 350 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 351 if (service != null) { 352 service.messageFromNative(event); 353 } else { 354 Log.w(TAG, "onCmdResult: Ignoring message because service not available: " + event); 355 } 356 } 357 358 private void onSubscriberInfo(String number, int type, byte[] address) { 359 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_SUBSCRIBER_INFO); 360 event.valueInt = type; 361 event.valueString = number; 362 event.device = getDevice(address); 363 if (DBG) { 364 Log.d(TAG, "onSubscriberInfo: address " + address + " event " + event); 365 } 366 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 367 if (service != null) { 368 service.messageFromNative(event); 369 } else { 370 Log.w(TAG, 371 "onSubscriberInfo: Ignoring message because service not available: " + event); 372 } 373 } 374 375 private void onInBandRing(int inBand, byte[] address) { 376 Log.w(TAG, "onInBandRing not supported"); 377 } 378 379 private void onLastVoiceTagNumber(String number, byte[] address) { 380 Log.w(TAG, "onLastVoiceTagNumber not supported"); 381 } 382 383 private void onRingIndication(byte[] address) { 384 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_RING_INDICATION); 385 event.device = getDevice(address); 386 if (DBG) { 387 Log.d(TAG, "onRingIndication: address " + address + " event " + event); 388 } 389 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 390 if (service != null) { 391 service.messageFromNative(event); 392 } else { 393 Log.w(TAG, 394 "onRingIndication: Ignoring message because service not available: " + event); 395 } 396 } 397} 398