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