1 /* 2 * Copyright (C) 2012 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 package com.android.bluetooth.hid; 18 19 import android.bluetooth.BluetoothDevice; 20 import android.bluetooth.BluetoothInputDevice; 21 import android.bluetooth.BluetoothProfile; 22 import android.bluetooth.IBluetooth; 23 import android.bluetooth.IBluetoothInputDevice; 24 import android.content.Intent; 25 import android.content.pm.PackageManager; 26 import android.os.Bundle; 27 import android.os.IBinder; 28 import android.os.Handler; 29 import android.os.Message; 30 import android.os.RemoteException; 31 import android.os.ServiceManager; 32 import android.provider.Settings; 33 import android.util.Log; 34 import com.android.bluetooth.btservice.AdapterService; 35 import com.android.bluetooth.btservice.ProfileService; 36 import com.android.bluetooth.Utils; 37 import java.util.ArrayList; 38 import java.util.Collections; 39 import java.util.HashMap; 40 import java.util.List; 41 import java.util.Map; 42 43 44 /** 45 * Provides Bluetooth Hid Host profile, as a service in 46 * the Bluetooth application. 47 * @hide 48 */ 49 public class HidService extends ProfileService { 50 private static final boolean DBG = false; 51 private static final String TAG = "HidService"; 52 53 private Map<BluetoothDevice, Integer> mInputDevices; 54 private boolean mNativeAvailable; 55 private static HidService sHidService; 56 private BluetoothDevice mTargetDevice = null; 57 58 private static final int MESSAGE_CONNECT = 1; 59 private static final int MESSAGE_DISCONNECT = 2; 60 private static final int MESSAGE_CONNECT_STATE_CHANGED = 3; 61 private static final int MESSAGE_GET_PROTOCOL_MODE = 4; 62 private static final int MESSAGE_VIRTUAL_UNPLUG = 5; 63 private static final int MESSAGE_ON_GET_PROTOCOL_MODE = 6; 64 private static final int MESSAGE_SET_PROTOCOL_MODE = 7; 65 private static final int MESSAGE_GET_REPORT = 8; 66 private static final int MESSAGE_ON_GET_REPORT = 9; 67 private static final int MESSAGE_SET_REPORT = 10; 68 private static final int MESSAGE_SEND_DATA = 11; 69 private static final int MESSAGE_ON_VIRTUAL_UNPLUG = 12; 70 71 static { 72 classInitNative(); 73 } 74 75 public String getName() { 76 return TAG; 77 } 78 79 public IProfileServiceBinder initBinder() { 80 return new BluetoothInputDeviceBinder(this); 81 } 82 83 protected boolean start() { 84 mInputDevices = Collections.synchronizedMap(new HashMap<BluetoothDevice, Integer>()); 85 initializeNative(); 86 mNativeAvailable=true; 87 setHidService(this); 88 return true; 89 } 90 91 protected boolean stop() { 92 if (DBG) log("Stopping Bluetooth HidService"); 93 return true; 94 } 95 96 protected boolean cleanup() { 97 if (mNativeAvailable) { 98 cleanupNative(); 99 mNativeAvailable=false; 100 } 101 102 if(mInputDevices != null) { 103 mInputDevices.clear(); 104 } 105 clearHidService(); 106 return true; 107 } 108 109 public static synchronized HidService getHidService(){ 110 if (sHidService != null && sHidService.isAvailable()) { 111 if (DBG) Log.d(TAG, "getHidService(): returning " + sHidService); 112 return sHidService; 113 } 114 if (DBG) { 115 if (sHidService == null) { 116 Log.d(TAG, "getHidService(): service is NULL"); 117 } else if (!(sHidService.isAvailable())) { 118 Log.d(TAG,"getHidService(): service is not available"); 119 } 120 } 121 return null; 122 } 123 124 private static synchronized void setHidService(HidService instance) { 125 if (instance != null && instance.isAvailable()) { 126 if (DBG) Log.d(TAG, "setHidService(): set to: " + sHidService); 127 sHidService = instance; 128 } else { 129 if (DBG) { 130 if (sHidService == null) { 131 Log.d(TAG, "setHidService(): service not available"); 132 } else if (!sHidService.isAvailable()) { 133 Log.d(TAG,"setHidService(): service is cleaning up"); 134 } 135 } 136 } 137 } 138 139 private static synchronized void clearHidService() { 140 sHidService = null; 141 } 142 143 144 private final Handler mHandler = new Handler() { 145 146 @Override 147 public void handleMessage(Message msg) { 148 switch (msg.what) { 149 case MESSAGE_CONNECT: 150 { 151 BluetoothDevice device = (BluetoothDevice) msg.obj; 152 if (!connectHidNative(Utils.getByteAddress(device)) ) { 153 broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTING); 154 broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED); 155 break; 156 } 157 mTargetDevice = device; 158 } 159 break; 160 case MESSAGE_DISCONNECT: 161 { 162 BluetoothDevice device = (BluetoothDevice) msg.obj; 163 if (!disconnectHidNative(Utils.getByteAddress(device)) ) { 164 broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTING); 165 broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED); 166 break; 167 } 168 } 169 break; 170 case MESSAGE_CONNECT_STATE_CHANGED: 171 { 172 BluetoothDevice device = getDevice((byte[]) msg.obj); 173 int halState = msg.arg1; 174 Integer prevStateInteger = mInputDevices.get(device); 175 int prevState = (prevStateInteger == null) ? 176 BluetoothInputDevice.STATE_DISCONNECTED :prevStateInteger; 177 if(DBG) Log.d(TAG, "MESSAGE_CONNECT_STATE_CHANGED newState:"+ 178 convertHalState(halState)+", prevState:"+prevState); 179 if(halState == CONN_STATE_CONNECTED && 180 prevState == BluetoothInputDevice.STATE_DISCONNECTED && 181 (!okToConnect(device))) { 182 if (DBG) Log.d(TAG,"Incoming HID connection rejected"); 183 disconnectHidNative(Utils.getByteAddress(device)); 184 } else { 185 broadcastConnectionState(device, convertHalState(halState)); 186 } 187 if (halState != CONN_STATE_CONNECTING) { 188 mTargetDevice = null; 189 } 190 else { 191 // CONN_STATE_CONNECTING is received only during 192 // local initiated connection. 193 mTargetDevice = device; 194 } 195 } 196 break; 197 case MESSAGE_GET_PROTOCOL_MODE: 198 { 199 BluetoothDevice device = (BluetoothDevice) msg.obj; 200 if(!getProtocolModeNative(Utils.getByteAddress(device)) ) { 201 Log.e(TAG, "Error: get protocol mode native returns false"); 202 } 203 } 204 break; 205 206 case MESSAGE_ON_GET_PROTOCOL_MODE: 207 { 208 BluetoothDevice device = getDevice((byte[]) msg.obj); 209 int protocolMode = msg.arg1; 210 broadcastProtocolMode(device, protocolMode); 211 } 212 break; 213 case MESSAGE_VIRTUAL_UNPLUG: 214 { 215 BluetoothDevice device = (BluetoothDevice) msg.obj; 216 if(!virtualUnPlugNative(Utils.getByteAddress(device))) { 217 Log.e(TAG, "Error: virtual unplug native returns false"); 218 } 219 } 220 break; 221 case MESSAGE_SET_PROTOCOL_MODE: 222 { 223 BluetoothDevice device = (BluetoothDevice) msg.obj; 224 byte protocolMode = (byte) msg.arg1; 225 log("sending set protocol mode(" + protocolMode + ")"); 226 if(!setProtocolModeNative(Utils.getByteAddress(device), protocolMode)) { 227 Log.e(TAG, "Error: set protocol mode native returns false"); 228 } 229 } 230 break; 231 case MESSAGE_GET_REPORT: 232 { 233 BluetoothDevice device = (BluetoothDevice) msg.obj; 234 Bundle data = msg.getData(); 235 byte reportType = data.getByte(BluetoothInputDevice.EXTRA_REPORT_TYPE); 236 byte reportId = data.getByte(BluetoothInputDevice.EXTRA_REPORT_ID); 237 int bufferSize = data.getInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE); 238 if(!getReportNative(Utils.getByteAddress(device), reportType, reportId, bufferSize)) { 239 Log.e(TAG, "Error: get report native returns false"); 240 } 241 } 242 break; 243 case MESSAGE_SET_REPORT: 244 { 245 BluetoothDevice device = (BluetoothDevice) msg.obj; 246 Bundle data = msg.getData(); 247 byte reportType = data.getByte(BluetoothInputDevice.EXTRA_REPORT_TYPE); 248 String report = data.getString(BluetoothInputDevice.EXTRA_REPORT); 249 if(!setReportNative(Utils.getByteAddress(device), reportType, report)) { 250 Log.e(TAG, "Error: set report native returns false"); 251 } 252 } 253 break; 254 case MESSAGE_SEND_DATA: 255 { 256 BluetoothDevice device = (BluetoothDevice) msg.obj; 257 Bundle data = msg.getData(); 258 String report = data.getString(BluetoothInputDevice.EXTRA_REPORT); 259 if(!sendDataNative(Utils.getByteAddress(device), report)) { 260 Log.e(TAG, "Error: send data native returns false"); 261 } 262 } 263 break; 264 case MESSAGE_ON_VIRTUAL_UNPLUG: 265 { 266 BluetoothDevice device = getDevice((byte[]) msg.obj); 267 int status = msg.arg1; 268 broadcastVirtualUnplugStatus(device, status); 269 } 270 break; 271 } 272 } 273 }; 274 275 /** 276 * Handlers for incoming service calls 277 */ 278 private static class BluetoothInputDeviceBinder extends IBluetoothInputDevice.Stub implements IProfileServiceBinder{ 279 private HidService mService; 280 public BluetoothInputDeviceBinder(HidService svc) { 281 mService = svc; 282 } 283 284 public boolean cleanup() { 285 mService = null; 286 return true; 287 } 288 289 private HidService getService() { 290 if (!Utils.checkCaller()) { 291 Log.w(TAG,"InputDevice call not allowed for non-active user"); 292 return null; 293 } 294 295 if (mService != null && mService.isAvailable()) { 296 return mService; 297 } 298 return null; 299 } 300 301 public boolean connect(BluetoothDevice device) { 302 HidService service = getService(); 303 if (service == null) return false; 304 return service.connect(device); 305 } 306 307 public boolean disconnect(BluetoothDevice device) { 308 HidService service = getService(); 309 if (service == null) return false; 310 return service.disconnect(device); 311 } 312 313 public int getConnectionState(BluetoothDevice device) { 314 HidService service = getService(); 315 if (service == null) return BluetoothInputDevice.STATE_DISCONNECTED; 316 return service.getConnectionState(device); 317 } 318 319 public List<BluetoothDevice> getConnectedDevices() { 320 return getDevicesMatchingConnectionStates( 321 new int[] {BluetoothProfile.STATE_CONNECTED}); 322 } 323 324 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 325 HidService service = getService(); 326 if (service == null) return new ArrayList<BluetoothDevice>(0); 327 return service.getDevicesMatchingConnectionStates(states); 328 } 329 330 public boolean setPriority(BluetoothDevice device, int priority) { 331 HidService service = getService(); 332 if (service == null) return false; 333 return service.setPriority(device, priority); 334 } 335 336 public int getPriority(BluetoothDevice device) { 337 HidService service = getService(); 338 if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED; 339 return service.getPriority(device); 340 } 341 342 /* The following APIs regarding test app for compliance */ 343 public boolean getProtocolMode(BluetoothDevice device) { 344 HidService service = getService(); 345 if (service == null) return false; 346 return service.getProtocolMode(device); 347 } 348 349 public boolean virtualUnplug(BluetoothDevice device) { 350 HidService service = getService(); 351 if (service == null) return false; 352 return service.virtualUnplug(device); 353 } 354 355 public boolean setProtocolMode(BluetoothDevice device, int protocolMode) { 356 HidService service = getService(); 357 if (service == null) return false; 358 return service.setProtocolMode(device, protocolMode); 359 } 360 361 public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) { 362 HidService service = getService(); 363 if (service == null) return false; 364 return service.getReport(device, reportType, reportId, bufferSize) ; 365 } 366 367 public boolean setReport(BluetoothDevice device, byte reportType, String report) { 368 HidService service = getService(); 369 if (service == null) return false; 370 return service.setReport(device, reportType, report); 371 } 372 373 public boolean sendData(BluetoothDevice device, String report) { 374 HidService service = getService(); 375 if (service == null) return false; 376 return service.sendData(device, report); 377 } 378 }; 379 380 //APIs 381 boolean connect(BluetoothDevice device) { 382 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 383 if (getConnectionState(device) != BluetoothInputDevice.STATE_DISCONNECTED) { 384 Log.e(TAG, "Hid Device not disconnected: " + device); 385 return false; 386 } 387 if (getPriority(device) == BluetoothInputDevice.PRIORITY_OFF) { 388 Log.e(TAG, "Hid Device PRIORITY_OFF: " + device); 389 return false; 390 } 391 392 Message msg = mHandler.obtainMessage(MESSAGE_CONNECT, device); 393 mHandler.sendMessage(msg); 394 return true; 395 } 396 397 boolean disconnect(BluetoothDevice device) { 398 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 399 Message msg = mHandler.obtainMessage(MESSAGE_DISCONNECT,device); 400 mHandler.sendMessage(msg); 401 return true; 402 } 403 404 int getConnectionState(BluetoothDevice device) { 405 if (mInputDevices.get(device) == null) { 406 return BluetoothInputDevice.STATE_DISCONNECTED; 407 } 408 return mInputDevices.get(device); 409 } 410 411 List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 412 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 413 List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>(); 414 415 for (BluetoothDevice device: mInputDevices.keySet()) { 416 int inputDeviceState = getConnectionState(device); 417 for (int state : states) { 418 if (state == inputDeviceState) { 419 inputDevices.add(device); 420 break; 421 } 422 } 423 } 424 return inputDevices; 425 } 426 427 public boolean setPriority(BluetoothDevice device, int priority) { 428 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 429 "Need BLUETOOTH_ADMIN permission"); 430 Settings.Global.putInt(getContentResolver(), 431 Settings.Global.getBluetoothInputDevicePriorityKey(device.getAddress()), 432 priority); 433 if (DBG) Log.d(TAG,"Saved priority " + device + " = " + priority); 434 return true; 435 } 436 437 public int getPriority(BluetoothDevice device) { 438 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 439 "Need BLUETOOTH_ADMIN permission"); 440 int priority = Settings.Global.getInt(getContentResolver(), 441 Settings.Global.getBluetoothInputDevicePriorityKey(device.getAddress()), 442 BluetoothProfile.PRIORITY_UNDEFINED); 443 return priority; 444 } 445 446 /* The following APIs regarding test app for compliance */ 447 boolean getProtocolMode(BluetoothDevice device) { 448 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 449 "Need BLUETOOTH_ADMIN permission"); 450 int state = this.getConnectionState(device); 451 if (state != BluetoothInputDevice.STATE_CONNECTED) { 452 return false; 453 } 454 Message msg = mHandler.obtainMessage(MESSAGE_GET_PROTOCOL_MODE,device); 455 mHandler.sendMessage(msg); 456 return true; 457 /* String objectPath = getObjectPathFromAddress(device.getAddress()); 458 return getProtocolModeInputDeviceNative(objectPath);*/ 459 } 460 461 boolean virtualUnplug(BluetoothDevice device) { 462 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 463 "Need BLUETOOTH_ADMIN permission"); 464 int state = this.getConnectionState(device); 465 if (state != BluetoothInputDevice.STATE_CONNECTED) { 466 return false; 467 } 468 Message msg = mHandler.obtainMessage(MESSAGE_VIRTUAL_UNPLUG,device); 469 mHandler.sendMessage(msg); 470 return true; 471 } 472 473 boolean setProtocolMode(BluetoothDevice device, int protocolMode) { 474 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 475 "Need BLUETOOTH_ADMIN permission"); 476 int state = this.getConnectionState(device); 477 if (state != BluetoothInputDevice.STATE_CONNECTED) { 478 return false; 479 } 480 Message msg = mHandler.obtainMessage(MESSAGE_SET_PROTOCOL_MODE); 481 msg.obj = device; 482 msg.arg1 = protocolMode; 483 mHandler.sendMessage(msg); 484 return true ; 485 } 486 487 boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) { 488 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 489 "Need BLUETOOTH_ADMIN permission"); 490 int state = this.getConnectionState(device); 491 if (state != BluetoothInputDevice.STATE_CONNECTED) { 492 return false; 493 } 494 Message msg = mHandler.obtainMessage(MESSAGE_GET_REPORT); 495 msg.obj = device; 496 Bundle data = new Bundle(); 497 data.putByte(BluetoothInputDevice.EXTRA_REPORT_TYPE, reportType); 498 data.putByte(BluetoothInputDevice.EXTRA_REPORT_ID, reportId); 499 data.putInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE, bufferSize); 500 msg.setData(data); 501 mHandler.sendMessage(msg); 502 return true ; 503 } 504 505 boolean setReport(BluetoothDevice device, byte reportType, String report) { 506 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 507 "Need BLUETOOTH_ADMIN permission"); 508 int state = this.getConnectionState(device); 509 if (state != BluetoothInputDevice.STATE_CONNECTED) { 510 return false; 511 } 512 Message msg = mHandler.obtainMessage(MESSAGE_SET_REPORT); 513 msg.obj = device; 514 Bundle data = new Bundle(); 515 data.putByte(BluetoothInputDevice.EXTRA_REPORT_TYPE, reportType); 516 data.putString(BluetoothInputDevice.EXTRA_REPORT, report); 517 msg.setData(data); 518 mHandler.sendMessage(msg); 519 return true ; 520 521 } 522 523 boolean sendData(BluetoothDevice device, String report) { 524 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 525 "Need BLUETOOTH_ADMIN permission"); 526 int state = this.getConnectionState(device); 527 if (state != BluetoothInputDevice.STATE_CONNECTED) { 528 return false; 529 } 530 531 return sendDataNative(Utils.getByteAddress(device), report); 532 /*Message msg = mHandler.obtainMessage(MESSAGE_SEND_DATA); 533 msg.obj = device; 534 Bundle data = new Bundle(); 535 data.putString(BluetoothInputDevice.EXTRA_REPORT, report); 536 msg.setData(data); 537 mHandler.sendMessage(msg); 538 return true ;*/ 539 } 540 541 private void onGetProtocolMode(byte[] address, int mode) { 542 Message msg = mHandler.obtainMessage(MESSAGE_ON_GET_PROTOCOL_MODE); 543 msg.obj = address; 544 msg.arg1 = mode; 545 mHandler.sendMessage(msg); 546 } 547 548 private void onVirtualUnplug(byte[] address, int status) { 549 Message msg = mHandler.obtainMessage(MESSAGE_ON_VIRTUAL_UNPLUG); 550 msg.obj = address; 551 msg.arg1 = status; 552 mHandler.sendMessage(msg); 553 } 554 555 private void onConnectStateChanged(byte[] address, int state) { 556 Message msg = mHandler.obtainMessage(MESSAGE_CONNECT_STATE_CHANGED); 557 msg.obj = address; 558 msg.arg1 = state; 559 mHandler.sendMessage(msg); 560 } 561 562 // This method does not check for error conditon (newState == prevState) 563 private void broadcastConnectionState(BluetoothDevice device, int newState) { 564 Integer prevStateInteger = mInputDevices.get(device); 565 int prevState = (prevStateInteger == null) ? BluetoothInputDevice.STATE_DISCONNECTED : 566 prevStateInteger; 567 if (prevState == newState) { 568 Log.w(TAG, "no state change: " + newState); 569 return; 570 } 571 mInputDevices.put(device, newState); 572 573 /* Notifying the connection state change of the profile before sending the intent for 574 connection state change, as it was causing a race condition, with the UI not being 575 updated with the correct connection state. */ 576 log("Connection state " + device + ": " + prevState + "->" + newState); 577 notifyProfileConnectionStateChanged(device, BluetoothProfile.INPUT_DEVICE, 578 newState, prevState); 579 Intent intent = new Intent(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED); 580 intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); 581 intent.putExtra(BluetoothProfile.EXTRA_STATE, newState); 582 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 583 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 584 sendBroadcast(intent, BLUETOOTH_PERM); 585 } 586 587 private void broadcastProtocolMode(BluetoothDevice device, int protocolMode) { 588 Intent intent = new Intent(BluetoothInputDevice.ACTION_PROTOCOL_MODE_CHANGED); 589 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 590 intent.putExtra(BluetoothInputDevice.EXTRA_PROTOCOL_MODE, protocolMode); 591 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 592 sendBroadcast(intent, BLUETOOTH_PERM); 593 if (DBG) log("Protocol Mode (" + device + "): " + protocolMode); 594 } 595 596 private void broadcastVirtualUnplugStatus(BluetoothDevice device, int status) { 597 Intent intent = new Intent(BluetoothInputDevice.ACTION_VIRTUAL_UNPLUG_STATUS); 598 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 599 intent.putExtra(BluetoothInputDevice.EXTRA_VIRTUAL_UNPLUG_STATUS, status); 600 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 601 sendBroadcast(intent, BLUETOOTH_PERM); 602 } 603 604 private boolean okToConnect(BluetoothDevice device) { 605 AdapterService adapterService = AdapterService.getAdapterService(); 606 //check if it is inbound connection in Quiet mode, priority and Bond status 607 //to decide if its ok to allow this connection 608 if((adapterService == null)|| 609 ((adapterService.isQuietModeEnabled()) &&(mTargetDevice == null)) || 610 (BluetoothProfile.PRIORITY_OFF == getPriority(device)) || 611 (device.getBondState() == BluetoothDevice.BOND_NONE)) 612 return false; 613 614 return true; 615 } 616 private static int convertHalState(int halState) { 617 switch (halState) { 618 case CONN_STATE_CONNECTED: 619 return BluetoothProfile.STATE_CONNECTED; 620 case CONN_STATE_CONNECTING: 621 return BluetoothProfile.STATE_CONNECTING; 622 case CONN_STATE_DISCONNECTED: 623 return BluetoothProfile.STATE_DISCONNECTED; 624 case CONN_STATE_DISCONNECTING: 625 return BluetoothProfile.STATE_DISCONNECTING; 626 default: 627 Log.e(TAG, "bad hid connection state: " + halState); 628 return BluetoothProfile.STATE_DISCONNECTED; 629 } 630 } 631 632 // Constants matching Hal header file bt_hh.h 633 // bthh_connection_state_t 634 private final static int CONN_STATE_CONNECTED = 0; 635 private final static int CONN_STATE_CONNECTING = 1; 636 private final static int CONN_STATE_DISCONNECTED = 2; 637 private final static int CONN_STATE_DISCONNECTING = 3; 638 639 private native static void classInitNative(); 640 private native void initializeNative(); 641 private native void cleanupNative(); 642 private native boolean connectHidNative(byte[] btAddress); 643 private native boolean disconnectHidNative(byte[] btAddress); 644 private native boolean getProtocolModeNative(byte[] btAddress); 645 private native boolean virtualUnPlugNative(byte[] btAddress); 646 private native boolean setProtocolModeNative(byte[] btAddress, byte protocolMode); 647 private native boolean getReportNative(byte[]btAddress, byte reportType, byte reportId, int bufferSize); 648 private native boolean setReportNative(byte[] btAddress, byte reportType, String report); 649 private native boolean sendDataNative(byte[] btAddress, String report); 650 } 651