135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie/* 2ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Copyright (C) 2012 The Android Open Source Project 3ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * 4ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Licensed under the Apache License, Version 2.0 (the "License"); 5ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * you may not use this file except in compliance with the License. 6ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * You may obtain a copy of the License at 7ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * 8ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * http://www.apache.org/licenses/LICENSE-2.0 9ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * 10ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Unless required by applicable law or agreed to in writing, software 11ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * distributed under the License is distributed on an "AS IS" BASIS, 12ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * See the License for the specific language governing permissions and 14ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * limitations under the License. 1535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie */ 1635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 1735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xiepackage com.android.bluetooth.hid; 1835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 1935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport android.bluetooth.BluetoothDevice; 2035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport android.bluetooth.BluetoothInputDevice; 2135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport android.bluetooth.BluetoothProfile; 2235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport android.bluetooth.IBluetooth; 2335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport android.bluetooth.IBluetoothInputDevice; 2435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport android.content.Intent; 2537510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xuimport android.content.pm.PackageManager; 2657addccaa75691f8eb6f35204d608a63695a9705Priti Agheraimport android.os.Bundle; 2735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport android.os.IBinder; 2835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport android.os.Handler; 2935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport android.os.Message; 3035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport android.os.RemoteException; 3135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport android.os.ServiceManager; 3235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport android.provider.Settings; 3335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport android.util.Log; 3437510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xuimport com.android.bluetooth.btservice.AdapterService; 3537510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xuimport com.android.bluetooth.btservice.ProfileService; 3637510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xuimport com.android.bluetooth.Utils; 3735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport java.util.ArrayList; 3835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport java.util.Collections; 3935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport java.util.HashMap; 4035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport java.util.List; 4135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieimport java.util.Map; 4237510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu 4335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 4435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie/** 45522003462124b08ef9345a6778df4089d202d6faHarish Paryani * Provides Bluetooth Hid Host profile, as a service in 4635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie * the Bluetooth application. 4735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie * @hide 4835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie */ 49b5cc776c9353a203cdde97e62b25f05d9633d14cfredcpublic class HidService extends ProfileService { 50fd1da115cbf09b7dd9bca3c7d3a4fb816a835dc5Matthew Xie private static final boolean DBG = false; 51b5cc776c9353a203cdde97e62b25f05d9633d14cfredc private static final String TAG = "HidService"; 5274ae04c73312403e89db0f8e9bd9601d403b4783fredc 5335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie private Map<BluetoothDevice, Integer> mInputDevices; 5474ae04c73312403e89db0f8e9bd9601d403b4783fredc private boolean mNativeAvailable; 554f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta private static HidService sHidService; 56ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta private BluetoothDevice mTargetDevice = null; 5735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 5835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie private static final int MESSAGE_CONNECT = 1; 5935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie private static final int MESSAGE_DISCONNECT = 2; 6035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie private static final int MESSAGE_CONNECT_STATE_CHANGED = 3; 6157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private static final int MESSAGE_GET_PROTOCOL_MODE = 4; 6257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private static final int MESSAGE_VIRTUAL_UNPLUG = 5; 6357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private static final int MESSAGE_ON_GET_PROTOCOL_MODE = 6; 6457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private static final int MESSAGE_SET_PROTOCOL_MODE = 7; 6557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private static final int MESSAGE_GET_REPORT = 8; 6657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private static final int MESSAGE_ON_GET_REPORT = 9; 6757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private static final int MESSAGE_SET_REPORT = 10; 6857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private static final int MESSAGE_SEND_DATA = 11; 6957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private static final int MESSAGE_ON_VIRTUAL_UNPLUG = 12; 7035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 7135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie static { 7235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie classInitNative(); 7335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 7435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 75b5cc776c9353a203cdde97e62b25f05d9633d14cfredc public String getName() { 76b5cc776c9353a203cdde97e62b25f05d9633d14cfredc return TAG; 7735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 7835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 7974ae04c73312403e89db0f8e9bd9601d403b4783fredc public IProfileServiceBinder initBinder() { 8074ae04c73312403e89db0f8e9bd9601d403b4783fredc return new BluetoothInputDeviceBinder(this); 8135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 8235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 83b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected boolean start() { 846654f5c903de510a70f9e72cd5ad7837b615d93ffredc mInputDevices = Collections.synchronizedMap(new HashMap<BluetoothDevice, Integer>()); 856654f5c903de510a70f9e72cd5ad7837b615d93ffredc initializeNative(); 8674ae04c73312403e89db0f8e9bd9601d403b4783fredc mNativeAvailable=true; 874f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta setHidService(this); 88b5cc776c9353a203cdde97e62b25f05d9633d14cfredc return true; 896654f5c903de510a70f9e72cd5ad7837b615d93ffredc } 906654f5c903de510a70f9e72cd5ad7837b615d93ffredc 91b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected boolean stop() { 9235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie if (DBG) log("Stopping Bluetooth HidService"); 9374ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 9474ae04c73312403e89db0f8e9bd9601d403b4783fredc } 9574ae04c73312403e89db0f8e9bd9601d403b4783fredc 9674ae04c73312403e89db0f8e9bd9601d403b4783fredc protected boolean cleanup() { 9774ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mNativeAvailable) { 9874ae04c73312403e89db0f8e9bd9601d403b4783fredc cleanupNative(); 9974ae04c73312403e89db0f8e9bd9601d403b4783fredc mNativeAvailable=false; 10074ae04c73312403e89db0f8e9bd9601d403b4783fredc } 1016654f5c903de510a70f9e72cd5ad7837b615d93ffredc 102b5cc776c9353a203cdde97e62b25f05d9633d14cfredc if(mInputDevices != null) { 103b5cc776c9353a203cdde97e62b25f05d9633d14cfredc mInputDevices.clear(); 1046654f5c903de510a70f9e72cd5ad7837b615d93ffredc } 1054f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta clearHidService(); 106b5cc776c9353a203cdde97e62b25f05d9633d14cfredc return true; 10735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 10835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 1094f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta public static synchronized HidService getHidService(){ 1104f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (sHidService != null && sHidService.isAvailable()) { 1114f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (DBG) Log.d(TAG, "getHidService(): returning " + sHidService); 1124f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta return sHidService; 1134f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1144f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (DBG) { 1154f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (sHidService == null) { 1164f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta Log.d(TAG, "getHidService(): service is NULL"); 1174f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } else if (!(sHidService.isAvailable())) { 1184f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta Log.d(TAG,"getHidService(): service is not available"); 1194f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1204f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1214f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta return null; 1224f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1234f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta 1244f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta private static synchronized void setHidService(HidService instance) { 1254f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (instance != null && instance.isAvailable()) { 1264f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (DBG) Log.d(TAG, "setHidService(): set to: " + sHidService); 1274f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta sHidService = instance; 1284f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } else { 1294f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (DBG) { 1304f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (sHidService == null) { 1314f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta Log.d(TAG, "setHidService(): service not available"); 1324f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } else if (!sHidService.isAvailable()) { 1334f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta Log.d(TAG,"setHidService(): service is cleaning up"); 1344f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1354f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1364f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1374f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1384f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta 1394f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta private static synchronized void clearHidService() { 1404f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta sHidService = null; 1414f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1424f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta 1434f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta 14435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie private final Handler mHandler = new Handler() { 14535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 14635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie @Override 14735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie public void handleMessage(Message msg) { 14835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie switch (msg.what) { 14935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie case MESSAGE_CONNECT: 15035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie { 15135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie BluetoothDevice device = (BluetoothDevice) msg.obj; 15274ae04c73312403e89db0f8e9bd9601d403b4783fredc if (!connectHidNative(Utils.getByteAddress(device)) ) { 15335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTING); 15435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED); 15535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie break; 15635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 157ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta mTargetDevice = device; 15835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 15935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie break; 16035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie case MESSAGE_DISCONNECT: 16135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie { 16235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie BluetoothDevice device = (BluetoothDevice) msg.obj; 16374ae04c73312403e89db0f8e9bd9601d403b4783fredc if (!disconnectHidNative(Utils.getByteAddress(device)) ) { 16435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTING); 16535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED); 16635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie break; 16735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 16835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 16935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie break; 17035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie case MESSAGE_CONNECT_STATE_CHANGED: 17135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie { 17235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie BluetoothDevice device = getDevice((byte[]) msg.obj); 17335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie int halState = msg.arg1; 17499a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M Integer prevStateInteger = mInputDevices.get(device); 17599a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M int prevState = (prevStateInteger == null) ? 17699a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M BluetoothInputDevice.STATE_DISCONNECTED :prevStateInteger; 17799a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M if(DBG) Log.d(TAG, "MESSAGE_CONNECT_STATE_CHANGED newState:"+ 17899a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M convertHalState(halState)+", prevState:"+prevState); 179ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta if(halState == CONN_STATE_CONNECTED && 180ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta prevState == BluetoothInputDevice.STATE_DISCONNECTED && 181ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta (!okToConnect(device))) { 1820f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) Log.d(TAG,"Incoming HID connection rejected"); 18399a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M disconnectHidNative(Utils.getByteAddress(device)); 18499a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M } else { 18599a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M broadcastConnectionState(device, convertHalState(halState)); 18699a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M } 187ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta if (halState != CONN_STATE_CONNECTING) { 188ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta mTargetDevice = null; 189ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta } 190ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta else { 191ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta // CONN_STATE_CONNECTING is received only during 192ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta // local initiated connection. 193ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta mTargetDevice = device; 194ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta } 19535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 19635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie break; 19757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera case MESSAGE_GET_PROTOCOL_MODE: 19857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera { 19957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera BluetoothDevice device = (BluetoothDevice) msg.obj; 20074ae04c73312403e89db0f8e9bd9601d403b4783fredc if(!getProtocolModeNative(Utils.getByteAddress(device)) ) { 20157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera Log.e(TAG, "Error: get protocol mode native returns false"); 20257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 20357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 20457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera break; 20557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera 20657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera case MESSAGE_ON_GET_PROTOCOL_MODE: 20757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera { 20857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera BluetoothDevice device = getDevice((byte[]) msg.obj); 20957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera int protocolMode = msg.arg1; 21057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera broadcastProtocolMode(device, protocolMode); 21157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 21257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera break; 21357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera case MESSAGE_VIRTUAL_UNPLUG: 21457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera { 21557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera BluetoothDevice device = (BluetoothDevice) msg.obj; 21674ae04c73312403e89db0f8e9bd9601d403b4783fredc if(!virtualUnPlugNative(Utils.getByteAddress(device))) { 21757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera Log.e(TAG, "Error: virtual unplug native returns false"); 21857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 21957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 22057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera break; 22157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera case MESSAGE_SET_PROTOCOL_MODE: 22257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera { 22357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera BluetoothDevice device = (BluetoothDevice) msg.obj; 22457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera byte protocolMode = (byte) msg.arg1; 22557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera log("sending set protocol mode(" + protocolMode + ")"); 22674ae04c73312403e89db0f8e9bd9601d403b4783fredc if(!setProtocolModeNative(Utils.getByteAddress(device), protocolMode)) { 22757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera Log.e(TAG, "Error: set protocol mode native returns false"); 22857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 22957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 23057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera break; 23157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera case MESSAGE_GET_REPORT: 23257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera { 23357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera BluetoothDevice device = (BluetoothDevice) msg.obj; 23457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera Bundle data = msg.getData(); 23557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera byte reportType = data.getByte(BluetoothInputDevice.EXTRA_REPORT_TYPE); 23657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera byte reportId = data.getByte(BluetoothInputDevice.EXTRA_REPORT_ID); 23757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera int bufferSize = data.getInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE); 23874ae04c73312403e89db0f8e9bd9601d403b4783fredc if(!getReportNative(Utils.getByteAddress(device), reportType, reportId, bufferSize)) { 23957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera Log.e(TAG, "Error: get report native returns false"); 24057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 24157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 24257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera break; 24357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera case MESSAGE_SET_REPORT: 24457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera { 24557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera BluetoothDevice device = (BluetoothDevice) msg.obj; 24657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera Bundle data = msg.getData(); 24757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera byte reportType = data.getByte(BluetoothInputDevice.EXTRA_REPORT_TYPE); 24857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera String report = data.getString(BluetoothInputDevice.EXTRA_REPORT); 24974ae04c73312403e89db0f8e9bd9601d403b4783fredc if(!setReportNative(Utils.getByteAddress(device), reportType, report)) { 25057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera Log.e(TAG, "Error: set report native returns false"); 25157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 25257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 25357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera break; 25457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera case MESSAGE_SEND_DATA: 25557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera { 25657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera BluetoothDevice device = (BluetoothDevice) msg.obj; 25757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera Bundle data = msg.getData(); 25857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera String report = data.getString(BluetoothInputDevice.EXTRA_REPORT); 25974ae04c73312403e89db0f8e9bd9601d403b4783fredc if(!sendDataNative(Utils.getByteAddress(device), report)) { 26057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera Log.e(TAG, "Error: send data native returns false"); 26157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 26257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 26357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera break; 26457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera case MESSAGE_ON_VIRTUAL_UNPLUG: 26557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera { 26657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera BluetoothDevice device = getDevice((byte[]) msg.obj); 26757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera int status = msg.arg1; 26857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera broadcastVirtualUnplugStatus(device, status); 26957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 27057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera break; 27135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 27235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 27335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie }; 27435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 27535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie /** 27635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie * Handlers for incoming service calls 27735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie */ 27874ae04c73312403e89db0f8e9bd9601d403b4783fredc private static class BluetoothInputDeviceBinder extends IBluetoothInputDevice.Stub implements IProfileServiceBinder{ 27974ae04c73312403e89db0f8e9bd9601d403b4783fredc private HidService mService; 28074ae04c73312403e89db0f8e9bd9601d403b4783fredc public BluetoothInputDeviceBinder(HidService svc) { 28174ae04c73312403e89db0f8e9bd9601d403b4783fredc mService = svc; 28274ae04c73312403e89db0f8e9bd9601d403b4783fredc } 28335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 28474ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean cleanup() { 28574ae04c73312403e89db0f8e9bd9601d403b4783fredc mService = null; 28635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return true; 28735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 28835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 28974ae04c73312403e89db0f8e9bd9601d403b4783fredc private HidService getService() { 29037510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu if (!Utils.checkCaller()) { 29137510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu Log.w(TAG,"InputDevice call not allowed for non-active user"); 29237510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu return null; 29337510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu } 29437510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu 29574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mService != null && mService.isAvailable()) { 29674ae04c73312403e89db0f8e9bd9601d403b4783fredc return mService; 29774ae04c73312403e89db0f8e9bd9601d403b4783fredc } 29874ae04c73312403e89db0f8e9bd9601d403b4783fredc return null; 29974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 30074ae04c73312403e89db0f8e9bd9601d403b4783fredc 30174ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean connect(BluetoothDevice device) { 30274ae04c73312403e89db0f8e9bd9601d403b4783fredc HidService service = getService(); 30374ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 30474ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.connect(device); 30574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 30674ae04c73312403e89db0f8e9bd9601d403b4783fredc 30735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie public boolean disconnect(BluetoothDevice device) { 30874ae04c73312403e89db0f8e9bd9601d403b4783fredc HidService service = getService(); 30974ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 31074ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.disconnect(device); 31135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 31235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 31335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie public int getConnectionState(BluetoothDevice device) { 31474ae04c73312403e89db0f8e9bd9601d403b4783fredc HidService service = getService(); 31574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return BluetoothInputDevice.STATE_DISCONNECTED; 31674ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.getConnectionState(device); 31735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 31835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 31935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie public List<BluetoothDevice> getConnectedDevices() { 32074ae04c73312403e89db0f8e9bd9601d403b4783fredc return getDevicesMatchingConnectionStates( 32135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie new int[] {BluetoothProfile.STATE_CONNECTED}); 32235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 32335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 32435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 32574ae04c73312403e89db0f8e9bd9601d403b4783fredc HidService service = getService(); 32674ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return new ArrayList<BluetoothDevice>(0); 32774ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.getDevicesMatchingConnectionStates(states); 32835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 32935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 33035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie public boolean setPriority(BluetoothDevice device, int priority) { 33174ae04c73312403e89db0f8e9bd9601d403b4783fredc HidService service = getService(); 33274ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 33374ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.setPriority(device, priority); 33435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 33535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 33635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie public int getPriority(BluetoothDevice device) { 33774ae04c73312403e89db0f8e9bd9601d403b4783fredc HidService service = getService(); 33874ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED; 33974ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.getPriority(device); 34035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 34174ae04c73312403e89db0f8e9bd9601d403b4783fredc 3421404ab28fd296373a98b766b0b01193985446eabHarish Paryani /* The following APIs regarding test app for compliance */ 34357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera public boolean getProtocolMode(BluetoothDevice device) { 34474ae04c73312403e89db0f8e9bd9601d403b4783fredc HidService service = getService(); 34574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 34674ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.getProtocolMode(device); 34757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 34857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera 34957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera public boolean virtualUnplug(BluetoothDevice device) { 35074ae04c73312403e89db0f8e9bd9601d403b4783fredc HidService service = getService(); 35174ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 35274ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.virtualUnplug(device); 35357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 35457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera 35557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera public boolean setProtocolMode(BluetoothDevice device, int protocolMode) { 35674ae04c73312403e89db0f8e9bd9601d403b4783fredc HidService service = getService(); 35774ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 35874ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.setProtocolMode(device, protocolMode); 35957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 36074ae04c73312403e89db0f8e9bd9601d403b4783fredc 36157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) { 36274ae04c73312403e89db0f8e9bd9601d403b4783fredc HidService service = getService(); 36374ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 36474ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.getReport(device, reportType, reportId, bufferSize) ; 36557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 36657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera 36757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera public boolean setReport(BluetoothDevice device, byte reportType, String report) { 36874ae04c73312403e89db0f8e9bd9601d403b4783fredc HidService service = getService(); 36974ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 37074ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.setReport(device, reportType, report); 37157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 37257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera 37357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera public boolean sendData(BluetoothDevice device, String report) { 37474ae04c73312403e89db0f8e9bd9601d403b4783fredc HidService service = getService(); 37574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 37674ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.sendData(device, report); 37774ae04c73312403e89db0f8e9bd9601d403b4783fredc } 37874ae04c73312403e89db0f8e9bd9601d403b4783fredc }; 37974ae04c73312403e89db0f8e9bd9601d403b4783fredc 38074ae04c73312403e89db0f8e9bd9601d403b4783fredc //APIs 38174ae04c73312403e89db0f8e9bd9601d403b4783fredc boolean connect(BluetoothDevice device) { 38274ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 38374ae04c73312403e89db0f8e9bd9601d403b4783fredc if (getConnectionState(device) != BluetoothInputDevice.STATE_DISCONNECTED) { 38474ae04c73312403e89db0f8e9bd9601d403b4783fredc Log.e(TAG, "Hid Device not disconnected: " + device); 38574ae04c73312403e89db0f8e9bd9601d403b4783fredc return false; 38674ae04c73312403e89db0f8e9bd9601d403b4783fredc } 38774ae04c73312403e89db0f8e9bd9601d403b4783fredc if (getPriority(device) == BluetoothInputDevice.PRIORITY_OFF) { 38874ae04c73312403e89db0f8e9bd9601d403b4783fredc Log.e(TAG, "Hid Device PRIORITY_OFF: " + device); 38974ae04c73312403e89db0f8e9bd9601d403b4783fredc return false; 39074ae04c73312403e89db0f8e9bd9601d403b4783fredc } 39174ae04c73312403e89db0f8e9bd9601d403b4783fredc 39274ae04c73312403e89db0f8e9bd9601d403b4783fredc Message msg = mHandler.obtainMessage(MESSAGE_CONNECT, device); 39374ae04c73312403e89db0f8e9bd9601d403b4783fredc mHandler.sendMessage(msg); 39474ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 39574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 39674ae04c73312403e89db0f8e9bd9601d403b4783fredc 39774ae04c73312403e89db0f8e9bd9601d403b4783fredc boolean disconnect(BluetoothDevice device) { 39874ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 39974ae04c73312403e89db0f8e9bd9601d403b4783fredc Message msg = mHandler.obtainMessage(MESSAGE_DISCONNECT,device); 40074ae04c73312403e89db0f8e9bd9601d403b4783fredc mHandler.sendMessage(msg); 40174ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 40274ae04c73312403e89db0f8e9bd9601d403b4783fredc } 40374ae04c73312403e89db0f8e9bd9601d403b4783fredc 40474ae04c73312403e89db0f8e9bd9601d403b4783fredc int getConnectionState(BluetoothDevice device) { 40574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mInputDevices.get(device) == null) { 40674ae04c73312403e89db0f8e9bd9601d403b4783fredc return BluetoothInputDevice.STATE_DISCONNECTED; 40774ae04c73312403e89db0f8e9bd9601d403b4783fredc } 40874ae04c73312403e89db0f8e9bd9601d403b4783fredc return mInputDevices.get(device); 40974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 41074ae04c73312403e89db0f8e9bd9601d403b4783fredc 41174ae04c73312403e89db0f8e9bd9601d403b4783fredc List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 41274ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 41374ae04c73312403e89db0f8e9bd9601d403b4783fredc List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>(); 41474ae04c73312403e89db0f8e9bd9601d403b4783fredc 41574ae04c73312403e89db0f8e9bd9601d403b4783fredc for (BluetoothDevice device: mInputDevices.keySet()) { 41674ae04c73312403e89db0f8e9bd9601d403b4783fredc int inputDeviceState = getConnectionState(device); 41774ae04c73312403e89db0f8e9bd9601d403b4783fredc for (int state : states) { 41874ae04c73312403e89db0f8e9bd9601d403b4783fredc if (state == inputDeviceState) { 41974ae04c73312403e89db0f8e9bd9601d403b4783fredc inputDevices.add(device); 42074ae04c73312403e89db0f8e9bd9601d403b4783fredc break; 42174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 42257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 42374ae04c73312403e89db0f8e9bd9601d403b4783fredc } 42474ae04c73312403e89db0f8e9bd9601d403b4783fredc return inputDevices; 42574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 42657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera 4274f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta public boolean setPriority(BluetoothDevice device, int priority) { 42874ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 42974ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH_ADMIN permission"); 430c7ead6d5827f3832b9210e92fab7597142059852Jeff Sharkey Settings.Global.putInt(getContentResolver(), 431c7ead6d5827f3832b9210e92fab7597142059852Jeff Sharkey Settings.Global.getBluetoothInputDevicePriorityKey(device.getAddress()), 43274ae04c73312403e89db0f8e9bd9601d403b4783fredc priority); 43374ae04c73312403e89db0f8e9bd9601d403b4783fredc if (DBG) Log.d(TAG,"Saved priority " + device + " = " + priority); 43474ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 43574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 43674ae04c73312403e89db0f8e9bd9601d403b4783fredc 4374f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta public int getPriority(BluetoothDevice device) { 43874ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 43974ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH_ADMIN permission"); 440c7ead6d5827f3832b9210e92fab7597142059852Jeff Sharkey int priority = Settings.Global.getInt(getContentResolver(), 441c7ead6d5827f3832b9210e92fab7597142059852Jeff Sharkey Settings.Global.getBluetoothInputDevicePriorityKey(device.getAddress()), 44274ae04c73312403e89db0f8e9bd9601d403b4783fredc BluetoothProfile.PRIORITY_UNDEFINED); 44374ae04c73312403e89db0f8e9bd9601d403b4783fredc return priority; 44474ae04c73312403e89db0f8e9bd9601d403b4783fredc } 44574ae04c73312403e89db0f8e9bd9601d403b4783fredc 44674ae04c73312403e89db0f8e9bd9601d403b4783fredc /* The following APIs regarding test app for compliance */ 44774ae04c73312403e89db0f8e9bd9601d403b4783fredc boolean getProtocolMode(BluetoothDevice device) { 44874ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 44974ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH_ADMIN permission"); 45074ae04c73312403e89db0f8e9bd9601d403b4783fredc int state = this.getConnectionState(device); 45174ae04c73312403e89db0f8e9bd9601d403b4783fredc if (state != BluetoothInputDevice.STATE_CONNECTED) { 45274ae04c73312403e89db0f8e9bd9601d403b4783fredc return false; 45357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 45474ae04c73312403e89db0f8e9bd9601d403b4783fredc Message msg = mHandler.obtainMessage(MESSAGE_GET_PROTOCOL_MODE,device); 45574ae04c73312403e89db0f8e9bd9601d403b4783fredc mHandler.sendMessage(msg); 45674ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 45774ae04c73312403e89db0f8e9bd9601d403b4783fredc /* String objectPath = getObjectPathFromAddress(device.getAddress()); 45874ae04c73312403e89db0f8e9bd9601d403b4783fredc return getProtocolModeInputDeviceNative(objectPath);*/ 45974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 46035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 46174ae04c73312403e89db0f8e9bd9601d403b4783fredc boolean virtualUnplug(BluetoothDevice device) { 46274ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 46374ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH_ADMIN permission"); 46474ae04c73312403e89db0f8e9bd9601d403b4783fredc int state = this.getConnectionState(device); 46574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (state != BluetoothInputDevice.STATE_CONNECTED) { 46674ae04c73312403e89db0f8e9bd9601d403b4783fredc return false; 46774ae04c73312403e89db0f8e9bd9601d403b4783fredc } 46874ae04c73312403e89db0f8e9bd9601d403b4783fredc Message msg = mHandler.obtainMessage(MESSAGE_VIRTUAL_UNPLUG,device); 46974ae04c73312403e89db0f8e9bd9601d403b4783fredc mHandler.sendMessage(msg); 47074ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 47174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 47274ae04c73312403e89db0f8e9bd9601d403b4783fredc 47374ae04c73312403e89db0f8e9bd9601d403b4783fredc boolean setProtocolMode(BluetoothDevice device, int protocolMode) { 47474ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 47574ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH_ADMIN permission"); 47674ae04c73312403e89db0f8e9bd9601d403b4783fredc int state = this.getConnectionState(device); 47774ae04c73312403e89db0f8e9bd9601d403b4783fredc if (state != BluetoothInputDevice.STATE_CONNECTED) { 47874ae04c73312403e89db0f8e9bd9601d403b4783fredc return false; 47974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 48074ae04c73312403e89db0f8e9bd9601d403b4783fredc Message msg = mHandler.obtainMessage(MESSAGE_SET_PROTOCOL_MODE); 48174ae04c73312403e89db0f8e9bd9601d403b4783fredc msg.obj = device; 48274ae04c73312403e89db0f8e9bd9601d403b4783fredc msg.arg1 = protocolMode; 48374ae04c73312403e89db0f8e9bd9601d403b4783fredc mHandler.sendMessage(msg); 48474ae04c73312403e89db0f8e9bd9601d403b4783fredc return true ; 48574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 48674ae04c73312403e89db0f8e9bd9601d403b4783fredc 48774ae04c73312403e89db0f8e9bd9601d403b4783fredc boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) { 48874ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 48974ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH_ADMIN permission"); 49074ae04c73312403e89db0f8e9bd9601d403b4783fredc int state = this.getConnectionState(device); 49174ae04c73312403e89db0f8e9bd9601d403b4783fredc if (state != BluetoothInputDevice.STATE_CONNECTED) { 49274ae04c73312403e89db0f8e9bd9601d403b4783fredc return false; 49374ae04c73312403e89db0f8e9bd9601d403b4783fredc } 49474ae04c73312403e89db0f8e9bd9601d403b4783fredc Message msg = mHandler.obtainMessage(MESSAGE_GET_REPORT); 49574ae04c73312403e89db0f8e9bd9601d403b4783fredc msg.obj = device; 49674ae04c73312403e89db0f8e9bd9601d403b4783fredc Bundle data = new Bundle(); 49774ae04c73312403e89db0f8e9bd9601d403b4783fredc data.putByte(BluetoothInputDevice.EXTRA_REPORT_TYPE, reportType); 49874ae04c73312403e89db0f8e9bd9601d403b4783fredc data.putByte(BluetoothInputDevice.EXTRA_REPORT_ID, reportId); 49974ae04c73312403e89db0f8e9bd9601d403b4783fredc data.putInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE, bufferSize); 50074ae04c73312403e89db0f8e9bd9601d403b4783fredc msg.setData(data); 50174ae04c73312403e89db0f8e9bd9601d403b4783fredc mHandler.sendMessage(msg); 50274ae04c73312403e89db0f8e9bd9601d403b4783fredc return true ; 50374ae04c73312403e89db0f8e9bd9601d403b4783fredc } 50474ae04c73312403e89db0f8e9bd9601d403b4783fredc 50574ae04c73312403e89db0f8e9bd9601d403b4783fredc boolean setReport(BluetoothDevice device, byte reportType, String report) { 50674ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 50774ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH_ADMIN permission"); 50874ae04c73312403e89db0f8e9bd9601d403b4783fredc int state = this.getConnectionState(device); 50974ae04c73312403e89db0f8e9bd9601d403b4783fredc if (state != BluetoothInputDevice.STATE_CONNECTED) { 51074ae04c73312403e89db0f8e9bd9601d403b4783fredc return false; 51174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 51274ae04c73312403e89db0f8e9bd9601d403b4783fredc Message msg = mHandler.obtainMessage(MESSAGE_SET_REPORT); 51374ae04c73312403e89db0f8e9bd9601d403b4783fredc msg.obj = device; 51474ae04c73312403e89db0f8e9bd9601d403b4783fredc Bundle data = new Bundle(); 51574ae04c73312403e89db0f8e9bd9601d403b4783fredc data.putByte(BluetoothInputDevice.EXTRA_REPORT_TYPE, reportType); 51674ae04c73312403e89db0f8e9bd9601d403b4783fredc data.putString(BluetoothInputDevice.EXTRA_REPORT, report); 51774ae04c73312403e89db0f8e9bd9601d403b4783fredc msg.setData(data); 51874ae04c73312403e89db0f8e9bd9601d403b4783fredc mHandler.sendMessage(msg); 51974ae04c73312403e89db0f8e9bd9601d403b4783fredc return true ; 52074ae04c73312403e89db0f8e9bd9601d403b4783fredc 52174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 52274ae04c73312403e89db0f8e9bd9601d403b4783fredc 52374ae04c73312403e89db0f8e9bd9601d403b4783fredc boolean sendData(BluetoothDevice device, String report) { 52474ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 52574ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH_ADMIN permission"); 52674ae04c73312403e89db0f8e9bd9601d403b4783fredc int state = this.getConnectionState(device); 52774ae04c73312403e89db0f8e9bd9601d403b4783fredc if (state != BluetoothInputDevice.STATE_CONNECTED) { 52874ae04c73312403e89db0f8e9bd9601d403b4783fredc return false; 52974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 53074ae04c73312403e89db0f8e9bd9601d403b4783fredc 53174ae04c73312403e89db0f8e9bd9601d403b4783fredc return sendDataNative(Utils.getByteAddress(device), report); 53274ae04c73312403e89db0f8e9bd9601d403b4783fredc /*Message msg = mHandler.obtainMessage(MESSAGE_SEND_DATA); 53374ae04c73312403e89db0f8e9bd9601d403b4783fredc msg.obj = device; 53474ae04c73312403e89db0f8e9bd9601d403b4783fredc Bundle data = new Bundle(); 53574ae04c73312403e89db0f8e9bd9601d403b4783fredc data.putString(BluetoothInputDevice.EXTRA_REPORT, report); 53674ae04c73312403e89db0f8e9bd9601d403b4783fredc msg.setData(data); 53774ae04c73312403e89db0f8e9bd9601d403b4783fredc mHandler.sendMessage(msg); 53874ae04c73312403e89db0f8e9bd9601d403b4783fredc return true ;*/ 53974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 54074ae04c73312403e89db0f8e9bd9601d403b4783fredc 54157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private void onGetProtocolMode(byte[] address, int mode) { 54257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera Message msg = mHandler.obtainMessage(MESSAGE_ON_GET_PROTOCOL_MODE); 54357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera msg.obj = address; 54457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera msg.arg1 = mode; 54557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera mHandler.sendMessage(msg); 54657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 54757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera 54857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private void onVirtualUnplug(byte[] address, int status) { 54957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera Message msg = mHandler.obtainMessage(MESSAGE_ON_VIRTUAL_UNPLUG); 55057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera msg.obj = address; 55157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera msg.arg1 = status; 55257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera mHandler.sendMessage(msg); 55357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 55457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera 55535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie private void onConnectStateChanged(byte[] address, int state) { 55635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie Message msg = mHandler.obtainMessage(MESSAGE_CONNECT_STATE_CHANGED); 55735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie msg.obj = address; 55835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie msg.arg1 = state; 55935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie mHandler.sendMessage(msg); 56035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 56135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 56235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie // This method does not check for error conditon (newState == prevState) 56335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie private void broadcastConnectionState(BluetoothDevice device, int newState) { 56435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie Integer prevStateInteger = mInputDevices.get(device); 56535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie int prevState = (prevStateInteger == null) ? BluetoothInputDevice.STATE_DISCONNECTED : 56635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie prevStateInteger; 56735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie if (prevState == newState) { 56835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie Log.w(TAG, "no state change: " + newState); 56935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return; 57035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 57135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie mInputDevices.put(device, newState); 57235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 573a25e9c65c2a0192b7b3d819e2b87704f1942aa2fSreenidhi T /* Notifying the connection state change of the profile before sending the intent for 574a25e9c65c2a0192b7b3d819e2b87704f1942aa2fSreenidhi T connection state change, as it was causing a race condition, with the UI not being 575a25e9c65c2a0192b7b3d819e2b87704f1942aa2fSreenidhi T updated with the correct connection state. */ 576fd1da115cbf09b7dd9bca3c7d3a4fb816a835dc5Matthew Xie log("Connection state " + device + ": " + prevState + "->" + newState); 577a25e9c65c2a0192b7b3d819e2b87704f1942aa2fSreenidhi T notifyProfileConnectionStateChanged(device, BluetoothProfile.INPUT_DEVICE, 578a25e9c65c2a0192b7b3d819e2b87704f1942aa2fSreenidhi T newState, prevState); 57935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie Intent intent = new Intent(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED); 58035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); 58135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie intent.putExtra(BluetoothProfile.EXTRA_STATE, newState); 58235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 58335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 58435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie sendBroadcast(intent, BLUETOOTH_PERM); 58535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 58635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 58757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private void broadcastProtocolMode(BluetoothDevice device, int protocolMode) { 58857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera Intent intent = new Intent(BluetoothInputDevice.ACTION_PROTOCOL_MODE_CHANGED); 58957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 59057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera intent.putExtra(BluetoothInputDevice.EXTRA_PROTOCOL_MODE, protocolMode); 59157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 59257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera sendBroadcast(intent, BLUETOOTH_PERM); 59357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera if (DBG) log("Protocol Mode (" + device + "): " + protocolMode); 59457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 59557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera 59657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private void broadcastVirtualUnplugStatus(BluetoothDevice device, int status) { 59757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera Intent intent = new Intent(BluetoothInputDevice.ACTION_VIRTUAL_UNPLUG_STATUS); 59857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 59957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera intent.putExtra(BluetoothInputDevice.EXTRA_VIRTUAL_UNPLUG_STATUS, status); 60057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 60157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera sendBroadcast(intent, BLUETOOTH_PERM); 60257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera } 60357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera 604ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta private boolean okToConnect(BluetoothDevice device) { 605ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta AdapterService adapterService = AdapterService.getAdapterService(); 606ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta //check if it is inbound connection in Quiet mode, priority and Bond status 607ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta //to decide if its ok to allow this connection 608ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta if((adapterService == null)|| 609ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta ((adapterService.isQuietModeEnabled()) &&(mTargetDevice == null)) || 610ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta (BluetoothProfile.PRIORITY_OFF == getPriority(device)) || 611ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta (device.getBondState() == BluetoothDevice.BOND_NONE)) 612ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta return false; 613ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta 614ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta return true; 615ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta } 61674ae04c73312403e89db0f8e9bd9601d403b4783fredc private static int convertHalState(int halState) { 61735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie switch (halState) { 61835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie case CONN_STATE_CONNECTED: 61935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return BluetoothProfile.STATE_CONNECTED; 62035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie case CONN_STATE_CONNECTING: 62135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return BluetoothProfile.STATE_CONNECTING; 62235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie case CONN_STATE_DISCONNECTED: 62335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return BluetoothProfile.STATE_DISCONNECTED; 62435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie case CONN_STATE_DISCONNECTING: 62535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return BluetoothProfile.STATE_DISCONNECTING; 62635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie default: 62735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie Log.e(TAG, "bad hid connection state: " + halState); 62835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return BluetoothProfile.STATE_DISCONNECTED; 62935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 63035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 63135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 63235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie // Constants matching Hal header file bt_hh.h 63335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie // bthh_connection_state_t 63435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie private final static int CONN_STATE_CONNECTED = 0; 63535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie private final static int CONN_STATE_CONNECTING = 1; 63635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie private final static int CONN_STATE_DISCONNECTED = 2; 63735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie private final static int CONN_STATE_DISCONNECTING = 3; 63835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 63935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie private native static void classInitNative(); 6406654f5c903de510a70f9e72cd5ad7837b615d93ffredc private native void initializeNative(); 6416654f5c903de510a70f9e72cd5ad7837b615d93ffredc private native void cleanupNative(); 64235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie private native boolean connectHidNative(byte[] btAddress); 64335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie private native boolean disconnectHidNative(byte[] btAddress); 64457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private native boolean getProtocolModeNative(byte[] btAddress); 64557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private native boolean virtualUnPlugNative(byte[] btAddress); 64657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private native boolean setProtocolModeNative(byte[] btAddress, byte protocolMode); 64757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private native boolean getReportNative(byte[]btAddress, byte reportType, byte reportId, int bufferSize); 64857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private native boolean setReportNative(byte[] btAddress, byte reportType, String report); 64957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera private native boolean sendDataNative(byte[] btAddress, String report); 65035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie} 651