HidService.java revision 3a04c35ba5f723ee4a6e1f1c37514691ebd1447d
1d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright/* 2d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * Copyright (C) 2012 The Android Open Source Project 3d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * 4d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * Licensed under the Apache License, Version 2.0 (the "License"); 5d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * you may not use this file except in compliance with the License. 6d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * You may obtain a copy of the License at 7d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * 8d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * http://www.apache.org/licenses/LICENSE-2.0 9d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * 10d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * Unless required by applicable law or agreed to in writing, software 11d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * distributed under the License is distributed on an "AS IS" BASIS, 12d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * See the License for the specific language governing permissions and 14d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * limitations under the License. 15d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright */ 16d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 17d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightpackage com.android.bluetooth.hid; 18d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 19d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.bluetooth.BluetoothDevice; 20d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.bluetooth.BluetoothInputDevice; 21d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.bluetooth.BluetoothProfile; 22d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.bluetooth.IBluetooth; 23d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.bluetooth.IBluetoothInputDevice; 24d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.content.Intent; 25d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.content.pm.PackageManager; 26d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.os.Bundle; 27d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.os.IBinder; 28d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.os.Handler; 29d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.os.Message; 30d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.os.RemoteException; 31d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.os.ServiceManager; 3206936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordonimport android.provider.Settings; 3306936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordonimport android.util.Log; 3406936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordonimport com.android.bluetooth.btservice.AdapterService; 3506936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordonimport com.android.bluetooth.btservice.ProfileService; 36d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport com.android.bluetooth.Utils; 37d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport java.util.ArrayList; 38d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport java.util.Collections; 39d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport java.util.HashMap; 40d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport java.util.List; 41d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport java.util.Map; 42d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 43d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 44d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright/** 45d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * Provides Bluetooth Hid Host profile, as a service in 46d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * the Bluetooth application. 47d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * @hide 48d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright */ 49d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightpublic class HidService extends ProfileService { 50d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final boolean DBG = false; 51d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final String TAG = "HidService"; 52d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 53d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private Map<BluetoothDevice, Integer> mInputDevices; 54d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private boolean mNativeAvailable; 55d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static HidService sHidService; 56d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private BluetoothDevice mTargetDevice = null; 57d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 58d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int MESSAGE_CONNECT = 1; 59d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int MESSAGE_DISCONNECT = 2; 60d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int MESSAGE_CONNECT_STATE_CHANGED = 3; 61d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int MESSAGE_GET_PROTOCOL_MODE = 4; 62d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int MESSAGE_VIRTUAL_UNPLUG = 5; 63d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int MESSAGE_ON_GET_PROTOCOL_MODE = 6; 64d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int MESSAGE_SET_PROTOCOL_MODE = 7; 65d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int MESSAGE_GET_REPORT = 8; 66d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int MESSAGE_ON_GET_REPORT = 9; 67d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int MESSAGE_SET_REPORT = 10; 68d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int MESSAGE_SEND_DATA = 11; 69d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int MESSAGE_ON_VIRTUAL_UNPLUG = 12; 70d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int MESSAGE_ON_HANDSHAKE = 13; 71d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 72d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright static { 73d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright classInitNative(); 74d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 75d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 76d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public String getName() { 77d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return TAG; 78d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 79d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 80d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public IProfileServiceBinder initBinder() { 81d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return new BluetoothInputDeviceBinder(this); 82d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 83d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 84d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright protected boolean start() { 85d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mInputDevices = Collections.synchronizedMap(new HashMap<BluetoothDevice, Integer>()); 86d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright initializeNative(); 87d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mNativeAvailable=true; 88d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright setHidService(this); 89d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return true; 90d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 91d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 92d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright protected boolean stop() { 93d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (DBG) log("Stopping Bluetooth HidService"); 94d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return true; 95d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 96d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 97d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright protected boolean cleanup() { 98d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (mNativeAvailable) { 99d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright cleanupNative(); 100d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mNativeAvailable=false; 101d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 102d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 103d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if(mInputDevices != null) { 104d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mInputDevices.clear(); 105d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 106d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright clearHidService(); 107d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return true; 108d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 109d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 110d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public static synchronized HidService getHidService(){ 11139efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath if (sHidService != null && sHidService.isAvailable()) { 112d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (DBG) Log.d(TAG, "getHidService(): returning " + sHidService); 113d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return sHidService; 11439efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath } 115d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (DBG) { 116d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (sHidService == null) { 11739efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath Log.d(TAG, "getHidService(): service is NULL"); 118d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } else if (!(sHidService.isAvailable())) { 119d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Log.d(TAG,"getHidService(): service is not available"); 12039efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath } 121d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 122d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return null; 123d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 124d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 125d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static synchronized void setHidService(HidService instance) { 126d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (instance != null && instance.isAvailable()) { 127d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (DBG) Log.d(TAG, "setHidService(): set to: " + sHidService); 128d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright sHidService = instance; 129d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } else { 130d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (DBG) { 131d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (sHidService == null) { 132d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Log.d(TAG, "setHidService(): service not available"); 133d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } else if (!sHidService.isAvailable()) { 134489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke Log.d(TAG,"setHidService(): service is cleaning up"); 135d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 136d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 137d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 138d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 139d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 140d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static synchronized void clearHidService() { 141d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright sHidService = null; 142d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 14306936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon 14406936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon 14506936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon private final Handler mHandler = new Handler() { 146d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 14706936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon @Override 14806936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon public void handleMessage(Message msg) { 14906936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon switch (msg.what) { 15006936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon case MESSAGE_CONNECT: 15106936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon { 15206936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon BluetoothDevice device = (BluetoothDevice) msg.obj; 15306936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon if (!connectHidNative(Utils.getByteAddress(device)) ) { 15406936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTING); 15506936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED); 156d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 157d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 158d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mTargetDevice = device; 159d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 160d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 161d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case MESSAGE_DISCONNECT: 162d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright { 163d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright BluetoothDevice device = (BluetoothDevice) msg.obj; 164d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (!disconnectHidNative(Utils.getByteAddress(device)) ) { 165d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTING); 166d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED); 167d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 168d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 169d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 170d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 171d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case MESSAGE_CONNECT_STATE_CHANGED: 172d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright { 173d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright BluetoothDevice device = getDevice((byte[]) msg.obj); 17471b16e81f9cbf2e288611f32c43ea7fb4a331fcfJason Gerecke int halState = msg.arg1; 17571b16e81f9cbf2e288611f32c43ea7fb4a331fcfJason Gerecke Integer prevStateInteger = mInputDevices.get(device); 176489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke int prevState = (prevStateInteger == null) ? 177489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke BluetoothInputDevice.STATE_DISCONNECTED :prevStateInteger; 178489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke if(DBG) Log.d(TAG, "MESSAGE_CONNECT_STATE_CHANGED newState:"+ 179489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke convertHalState(halState)+", prevState:"+prevState); 180489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke if(halState == CONN_STATE_CONNECTED && 18112d6baa9b832f16a28f048ed5ffab75a76ed9c41Jason Gerecke prevState == BluetoothInputDevice.STATE_DISCONNECTED && 18212d6baa9b832f16a28f048ed5ffab75a76ed9c41Jason Gerecke (!okToConnect(device))) { 18378f97b3263053c388080a738b56499139517c3b6Vladislav Kaznacheev if (DBG) Log.d(TAG,"Incoming HID connection rejected"); 18478f97b3263053c388080a738b56499139517c3b6Vladislav Kaznacheev disconnectHidNative(Utils.getByteAddress(device)); 18578f97b3263053c388080a738b56499139517c3b6Vladislav Kaznacheev } else { 18678f97b3263053c388080a738b56499139517c3b6Vladislav Kaznacheev broadcastConnectionState(device, convertHalState(halState)); 187d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 18806936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon if (halState != CONN_STATE_CONNECTING) { 18906936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon mTargetDevice = null; 19006936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon } 19106936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon else { 19206936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon // CONN_STATE_CONNECTING is received only during 19306936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon // local initiated connection. 19406936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon mTargetDevice = device; 19506936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon } 19606936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon } 19706936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon break; 19806936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon case MESSAGE_GET_PROTOCOL_MODE: 19906936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon { 20006936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon BluetoothDevice device = (BluetoothDevice) msg.obj; 20106936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon if(!getProtocolModeNative(Utils.getByteAddress(device)) ) { 20206936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon Log.e(TAG, "Error: get protocol mode native returns false"); 20306936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon } 20406936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon } 20506936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon break; 20606936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon 20706936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon case MESSAGE_ON_GET_PROTOCOL_MODE: 20806936feb07bf6fbef262e4adebeb8e53910d8cf4Santos Cordon { 209d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright BluetoothDevice device = getDevice((byte[]) msg.obj); 210d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int protocolMode = msg.arg1; 211d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright broadcastProtocolMode(device, protocolMode); 212d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 213d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 214d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case MESSAGE_VIRTUAL_UNPLUG: 215d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright { 216d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright BluetoothDevice device = (BluetoothDevice) msg.obj; 217d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if(!virtualUnPlugNative(Utils.getByteAddress(device))) { 218d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Log.e(TAG, "Error: virtual unplug native returns false"); 219d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 220d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 22139efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath break; 222d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case MESSAGE_SET_PROTOCOL_MODE: 223d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright { 224d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright BluetoothDevice device = (BluetoothDevice) msg.obj; 22539efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath byte protocolMode = (byte) msg.arg1; 226d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright log("sending set protocol mode(" + protocolMode + ")"); 227d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if(!setProtocolModeNative(Utils.getByteAddress(device), protocolMode)) { 228d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Log.e(TAG, "Error: set protocol mode native returns false"); 229d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 230d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 231d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 232d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case MESSAGE_GET_REPORT: 233d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright { 234d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright BluetoothDevice device = (BluetoothDevice) msg.obj; 235d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Bundle data = msg.getData(); 236d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright byte reportType = data.getByte(BluetoothInputDevice.EXTRA_REPORT_TYPE); 237d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright byte reportId = data.getByte(BluetoothInputDevice.EXTRA_REPORT_ID); 238d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int bufferSize = data.getInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE); 239d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if(!getReportNative(Utils.getByteAddress(device), reportType, reportId, bufferSize)) { 240d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Log.e(TAG, "Error: get report native returns false"); 241d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 242d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 243d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 244d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case MESSAGE_ON_GET_REPORT: 245d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright { 246d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright BluetoothDevice device = getDevice((byte[])msg.obj); 247d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Bundle data = msg.getData(); 248d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright byte[] report = data.getByteArray(BluetoothInputDevice.EXTRA_REPORT); 249d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int bufferSize = data.getInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE); 250d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright broadcastReport(device, report, bufferSize); 251d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 252d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 253d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case MESSAGE_ON_HANDSHAKE: 254d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright { 255d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright BluetoothDevice device = getDevice((byte[])msg.obj); 256d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int status = msg.arg1; 257d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright broadcastHandshake(device, status); 258d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 259d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 260d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case MESSAGE_SET_REPORT: 261d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright { 262d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright BluetoothDevice device = (BluetoothDevice) msg.obj; 263d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Bundle data = msg.getData(); 264d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright byte reportType = data.getByte(BluetoothInputDevice.EXTRA_REPORT_TYPE); 265d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright String report = data.getString(BluetoothInputDevice.EXTRA_REPORT); 266d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if(!setReportNative(Utils.getByteAddress(device), reportType, report)) { 267d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Log.e(TAG, "Error: set report native returns false"); 268d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 269d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 270d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 271d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case MESSAGE_SEND_DATA: 272d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright { 273d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright BluetoothDevice device = (BluetoothDevice) msg.obj; 274d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Bundle data = msg.getData(); 275d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright String report = data.getString(BluetoothInputDevice.EXTRA_REPORT); 276d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if(!sendDataNative(Utils.getByteAddress(device), report)) { 277d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Log.e(TAG, "Error: send data native returns false"); 278d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 279d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 280d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 281d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case MESSAGE_ON_VIRTUAL_UNPLUG: 282d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright { 283d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright BluetoothDevice device = getDevice((byte[]) msg.obj); 284d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int status = msg.arg1; 285d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright broadcastVirtualUnplugStatus(device, status); 286d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 287d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 288d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 289d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 290d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright }; 291d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 292d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright /** 293d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * Handlers for incoming service calls 294d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright */ 295d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static class BluetoothInputDeviceBinder extends IBluetoothInputDevice.Stub implements IProfileServiceBinder{ 296d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private HidService mService; 297d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public BluetoothInputDeviceBinder(HidService svc) { 298d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mService = svc; 299d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 300d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 301d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public boolean cleanup() { 302d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mService = null; 303d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return true; 304d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 305d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 306d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private HidService getService() { 307d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (!Utils.checkCaller()) { 308d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Log.w(TAG,"InputDevice call not allowed for non-active user"); 309d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return null; 310d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 311d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 312d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (mService != null && mService.isAvailable()) { 313d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return mService; 314d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 315d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return null; 316d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 317d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 318d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public boolean connect(BluetoothDevice device) { 319d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright HidService service = getService(); 320d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (service == null) return false; 321d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return service.connect(device); 322d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 323d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 324d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public boolean disconnect(BluetoothDevice device) { 325d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright HidService service = getService(); 326d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (service == null) return false; 327d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return service.disconnect(device); 328d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 329d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 330d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public int getConnectionState(BluetoothDevice device) { 331d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright HidService service = getService(); 332d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (service == null) return BluetoothInputDevice.STATE_DISCONNECTED; 333d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return service.getConnectionState(device); 334d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 335d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 336d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public List<BluetoothDevice> getConnectedDevices() { 337d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return getDevicesMatchingConnectionStates( 338d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright new int[] {BluetoothProfile.STATE_CONNECTED}); 339d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 340d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 341d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 342d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright HidService service = getService(); 343d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (service == null) return new ArrayList<BluetoothDevice>(0); 344d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return service.getDevicesMatchingConnectionStates(states); 345d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 346d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 347d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public boolean setPriority(BluetoothDevice device, int priority) { 348d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright HidService service = getService(); 349d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (service == null) return false; 350d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return service.setPriority(device, priority); 3516ca70efdaef8c07e91692101c7a3ae35dc1e0cbbChih-Hung Hsieh } 352d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 353d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public int getPriority(BluetoothDevice device) { 354d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright HidService service = getService(); 355d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED; 356d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return service.getPriority(device); 357d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 358d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 359d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright /* The following APIs regarding test app for compliance */ 360d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public boolean getProtocolMode(BluetoothDevice device) { 361d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright HidService service = getService(); 362d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (service == null) return false; 363d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return service.getProtocolMode(device); 364d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 365d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 366d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public boolean virtualUnplug(BluetoothDevice device) { 367d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright HidService service = getService(); 368d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (service == null) return false; 369d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return service.virtualUnplug(device); 370d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 371d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 372d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public boolean setProtocolMode(BluetoothDevice device, int protocolMode) { 373d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright HidService service = getService(); 374d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (service == null) return false; 375d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return service.setProtocolMode(device, protocolMode); 376d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 377d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 378d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) { 379d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright HidService service = getService(); 380d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (service == null) return false; 381d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return service.getReport(device, reportType, reportId, bufferSize) ; 382d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 383d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 384d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public boolean setReport(BluetoothDevice device, byte reportType, String report) { 385d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright HidService service = getService(); 386d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (service == null) return false; 387d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return service.setReport(device, reportType, report); 388d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 389d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 390d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public boolean sendData(BluetoothDevice device, String report) { 391d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright HidService service = getService(); 392d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (service == null) return false; 393d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return service.sendData(device, report); 394d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 395d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright }; 396d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 397d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright //APIs 398d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright boolean connect(BluetoothDevice device) { 399d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 400d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (getConnectionState(device) != BluetoothInputDevice.STATE_DISCONNECTED) { 401d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Log.e(TAG, "Hid Device not disconnected: " + device); 402d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return false; 403d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 404d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (getPriority(device) == BluetoothInputDevice.PRIORITY_OFF) { 405d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Log.e(TAG, "Hid Device PRIORITY_OFF: " + device); 406d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return false; 407d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 408d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 409d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Message msg = mHandler.obtainMessage(MESSAGE_CONNECT, device); 410d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler.sendMessage(msg); 411d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return true; 412d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 413d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 414d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright boolean disconnect(BluetoothDevice device) { 415d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 416d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Message msg = mHandler.obtainMessage(MESSAGE_DISCONNECT,device); 417d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler.sendMessage(msg); 418d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return true; 419d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 420d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 421d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int getConnectionState(BluetoothDevice device) { 422d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (mInputDevices.get(device) == null) { 423d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return BluetoothInputDevice.STATE_DISCONNECTED; 424d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 425d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return mInputDevices.get(device); 426d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 427d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 428d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 429d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 430d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>(); 431d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 432d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright for (BluetoothDevice device: mInputDevices.keySet()) { 433d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int inputDeviceState = getConnectionState(device); 434d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright for (int state : states) { 435d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (state == inputDeviceState) { 436d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright inputDevices.add(device); 437d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 438d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 439d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 440d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 441d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return inputDevices; 442d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 443d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 444d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public boolean setPriority(BluetoothDevice device, int priority) { 445d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 446d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright "Need BLUETOOTH_ADMIN permission"); 447d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Settings.Global.putInt(getContentResolver(), 448d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Settings.Global.getBluetoothInputDevicePriorityKey(device.getAddress()), 449d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright priority); 450d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (DBG) Log.d(TAG,"Saved priority " + device + " = " + priority); 451d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return true; 452d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 453d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 454d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public int getPriority(BluetoothDevice device) { 455d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 456d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright "Need BLUETOOTH_ADMIN permission"); 457d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int priority = Settings.Global.getInt(getContentResolver(), 458d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Settings.Global.getBluetoothInputDevicePriorityKey(device.getAddress()), 459d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright BluetoothProfile.PRIORITY_UNDEFINED); 460d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return priority; 461d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 462d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 463d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright /* The following APIs regarding test app for compliance */ 464d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright boolean getProtocolMode(BluetoothDevice device) { 465d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 466d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright "Need BLUETOOTH_ADMIN permission"); 467d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int state = this.getConnectionState(device); 468d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (state != BluetoothInputDevice.STATE_CONNECTED) { 469d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return false; 470d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 471d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Message msg = mHandler.obtainMessage(MESSAGE_GET_PROTOCOL_MODE,device); 472d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler.sendMessage(msg); 473d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return true; 474d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright /* String objectPath = getObjectPathFromAddress(device.getAddress()); 475d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return getProtocolModeInputDeviceNative(objectPath);*/ 476d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 477d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 478d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright boolean virtualUnplug(BluetoothDevice device) { 479d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 480d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright "Need BLUETOOTH_ADMIN permission"); 481d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int state = this.getConnectionState(device); 482d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (state != BluetoothInputDevice.STATE_CONNECTED) { 483d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return false; 484d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 485d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Message msg = mHandler.obtainMessage(MESSAGE_VIRTUAL_UNPLUG,device); 486d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler.sendMessage(msg); 487d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return true; 488d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 489d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 490d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright boolean setProtocolMode(BluetoothDevice device, int protocolMode) { 491d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 492d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright "Need BLUETOOTH_ADMIN permission"); 493d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int state = this.getConnectionState(device); 494d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (state != BluetoothInputDevice.STATE_CONNECTED) { 495d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return false; 496d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 497d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Message msg = mHandler.obtainMessage(MESSAGE_SET_PROTOCOL_MODE); 498d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.obj = device; 499d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.arg1 = protocolMode; 500d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler.sendMessage(msg); 501d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return true ; 502d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 503d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 504d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) { 505d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 506d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright "Need BLUETOOTH_ADMIN permission"); 50739efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath int state = this.getConnectionState(device); 508d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (state != BluetoothInputDevice.STATE_CONNECTED) { 509d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return false; 510d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 511d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Message msg = mHandler.obtainMessage(MESSAGE_GET_REPORT); 512d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.obj = device; 513d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Bundle data = new Bundle(); 514d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright data.putByte(BluetoothInputDevice.EXTRA_REPORT_TYPE, reportType); 515d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright data.putByte(BluetoothInputDevice.EXTRA_REPORT_ID, reportId); 516d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright data.putInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE, bufferSize); 517d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.setData(data); 518d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler.sendMessage(msg); 519d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return true ; 520d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 521d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 522d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright boolean setReport(BluetoothDevice device, byte reportType, String report) { 523d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 524d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright "Need BLUETOOTH_ADMIN permission"); 525d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int state = this.getConnectionState(device); 526d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (state != BluetoothInputDevice.STATE_CONNECTED) { 527d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return false; 528d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 529d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Message msg = mHandler.obtainMessage(MESSAGE_SET_REPORT); 530d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.obj = device; 531d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Bundle data = new Bundle(); 532d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright data.putByte(BluetoothInputDevice.EXTRA_REPORT_TYPE, reportType); 533d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright data.putString(BluetoothInputDevice.EXTRA_REPORT, report); 534d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.setData(data); 535d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler.sendMessage(msg); 536d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return true ; 537d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 538d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 539d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 54039efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath boolean sendData(BluetoothDevice device, String report) { 541d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 542d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright "Need BLUETOOTH_ADMIN permission"); 543d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int state = this.getConnectionState(device); 5440faaa0bd7aa5dadea7c365fbb1f186da6eb097efDmitry Torokhov if (state != BluetoothInputDevice.STATE_CONNECTED) { 5450faaa0bd7aa5dadea7c365fbb1f186da6eb097efDmitry Torokhov return false; 5460faaa0bd7aa5dadea7c365fbb1f186da6eb097efDmitry Torokhov } 547d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 548d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return sendDataNative(Utils.getByteAddress(device), report); 549d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright /*Message msg = mHandler.obtainMessage(MESSAGE_SEND_DATA); 550d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.obj = device; 551d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Bundle data = new Bundle(); 552d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright data.putString(BluetoothInputDevice.EXTRA_REPORT, report); 553d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.setData(data); 554d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler.sendMessage(msg); 555d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return true ;*/ 556d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 5570faaa0bd7aa5dadea7c365fbb1f186da6eb097efDmitry Torokhov 5580faaa0bd7aa5dadea7c365fbb1f186da6eb097efDmitry Torokhov private void onGetProtocolMode(byte[] address, int mode) { 5590faaa0bd7aa5dadea7c365fbb1f186da6eb097efDmitry Torokhov Message msg = mHandler.obtainMessage(MESSAGE_ON_GET_PROTOCOL_MODE); 560d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.obj = address; 561d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.arg1 = mode; 562d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler.sendMessage(msg); 563d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 564d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 565d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private void onGetReport(byte[] address, byte[] report, int rpt_size) { 566d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Message msg = mHandler.obtainMessage(MESSAGE_ON_GET_REPORT); 567d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.obj = address; 568d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Bundle data = new Bundle(); 569d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright data.putByteArray(BluetoothInputDevice.EXTRA_REPORT, report); 570d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright data.putInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE, rpt_size); 571d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.setData(data); 572d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler.sendMessage(msg); 573d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 574d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 575d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private void onHandshake(byte[] address, int status) { 576d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Message msg = mHandler.obtainMessage(MESSAGE_ON_HANDSHAKE); 577d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.obj = address; 578d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.arg1 = status; 579d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler.sendMessage(msg); 580d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 581d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 58239efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath private void onVirtualUnplug(byte[] address, int status) { 583d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Message msg = mHandler.obtainMessage(MESSAGE_ON_VIRTUAL_UNPLUG); 584d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.obj = address; 585d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.arg1 = status; 586d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler.sendMessage(msg); 587d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 588d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 589d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private void onConnectStateChanged(byte[] address, int state) { 59039efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath Message msg = mHandler.obtainMessage(MESSAGE_CONNECT_STATE_CHANGED); 591d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.obj = address; 592d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright msg.arg1 = state; 593d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler.sendMessage(msg); 594d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 595d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 596d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright // This method does not check for error conditon (newState == prevState) 597d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private void broadcastConnectionState(BluetoothDevice device, int newState) { 598d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Integer prevStateInteger = mInputDevices.get(device); 599d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int prevState = (prevStateInteger == null) ? BluetoothInputDevice.STATE_DISCONNECTED : 600d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright prevStateInteger; 601d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (prevState == newState) { 602d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Log.w(TAG, "no state change: " + newState); 603d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return; 604d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 605d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mInputDevices.put(device, newState); 606d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 607d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright /* Notifying the connection state change of the profile before sending the intent for 608d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright connection state change, as it was causing a race condition, with the UI not being 609d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright updated with the correct connection state. */ 610d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright log("Connection state " + device + ": " + prevState + "->" + newState); 611d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright notifyProfileConnectionStateChanged(device, BluetoothProfile.INPUT_DEVICE, 612d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright newState, prevState); 613d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Intent intent = new Intent(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED); 614d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); 615d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.putExtra(BluetoothProfile.EXTRA_STATE, newState); 616d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 617d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 618d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright sendBroadcast(intent, BLUETOOTH_PERM); 619d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 620d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 621d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private void broadcastHandshake(BluetoothDevice device, int status) { 622d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Intent intent = new Intent(BluetoothInputDevice.ACTION_HANDSHAKE); 623d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 624d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.putExtra(BluetoothInputDevice.EXTRA_STATUS, status); 625d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 626d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright sendBroadcast(intent, BLUETOOTH_PERM); 627d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 628d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 629d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private void broadcastProtocolMode(BluetoothDevice device, int protocolMode) { 630d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Intent intent = new Intent(BluetoothInputDevice.ACTION_PROTOCOL_MODE_CHANGED); 631d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 632d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.putExtra(BluetoothInputDevice.EXTRA_PROTOCOL_MODE, protocolMode); 633d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 634d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright sendBroadcast(intent, BLUETOOTH_PERM); 635d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (DBG) log("Protocol Mode (" + device + "): " + protocolMode); 636d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 637d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 638d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private void broadcastReport(BluetoothDevice device, byte[] report, int rpt_size) { 639d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Intent intent = new Intent(BluetoothInputDevice.ACTION_REPORT); 640d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 641d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.putExtra(BluetoothInputDevice.EXTRA_REPORT, report); 642d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.putExtra(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE, rpt_size); 643d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 644d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright sendBroadcast(intent, BLUETOOTH_PERM); 645d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 646d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 647d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private void broadcastVirtualUnplugStatus(BluetoothDevice device, int status) { 648d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Intent intent = new Intent(BluetoothInputDevice.ACTION_VIRTUAL_UNPLUG_STATUS); 649d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 650d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.putExtra(BluetoothInputDevice.EXTRA_VIRTUAL_UNPLUG_STATUS, status); 651d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 652d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright sendBroadcast(intent, BLUETOOTH_PERM); 653d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 654d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 655d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private boolean okToConnect(BluetoothDevice device) { 656d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright AdapterService adapterService = AdapterService.getAdapterService(); 657d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright //check if it is inbound connection in Quiet mode, priority and Bond status 658d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright //to decide if its ok to allow this connection 659d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if((adapterService == null)|| 660d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright ((adapterService.isQuietModeEnabled()) &&(mTargetDevice == null)) || 661d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright (BluetoothProfile.PRIORITY_OFF == getPriority(device)) || 662d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright (device.getBondState() == BluetoothDevice.BOND_NONE)) 663d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return false; 664d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 665d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return true; 666d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 667d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static int convertHalState(int halState) { 668d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright switch (halState) { 669d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case CONN_STATE_CONNECTED: 670d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return BluetoothProfile.STATE_CONNECTED; 671d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case CONN_STATE_CONNECTING: 672d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return BluetoothProfile.STATE_CONNECTING; 673d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case CONN_STATE_DISCONNECTED: 674d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return BluetoothProfile.STATE_DISCONNECTED; 675d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case CONN_STATE_DISCONNECTING: 676d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return BluetoothProfile.STATE_DISCONNECTING; 677d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright default: 678d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright Log.e(TAG, "bad hid connection state: " + halState); 679d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return BluetoothProfile.STATE_DISCONNECTED; 680d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 681d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 682d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 683d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright // Constants matching Hal header file bt_hh.h 684d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright // bthh_connection_state_t 685d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private final static int CONN_STATE_CONNECTED = 0; 686d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private final static int CONN_STATE_CONNECTING = 1; 687d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private final static int CONN_STATE_DISCONNECTED = 2; 688d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private final static int CONN_STATE_DISCONNECTING = 3; 689d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 690d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private native static void classInitNative(); 691d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private native void initializeNative(); 692d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private native void cleanupNative(); 693d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private native boolean connectHidNative(byte[] btAddress); 694d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private native boolean disconnectHidNative(byte[] btAddress); 695d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private native boolean getProtocolModeNative(byte[] btAddress); 696d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private native boolean virtualUnPlugNative(byte[] btAddress); 697d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private native boolean setProtocolModeNative(byte[] btAddress, byte protocolMode); 698d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private native boolean getReportNative(byte[]btAddress, byte reportType, byte reportId, int bufferSize); 699d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private native boolean setReportNative(byte[] btAddress, byte reportType, String report); 700d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private native boolean sendDataNative(byte[] btAddress, String report); 701d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright} 702d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright