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;
703a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen    private static final int MESSAGE_ON_HANDSHAKE = 13;
7135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
7235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    static {
7335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        classInitNative();
7435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    }
7535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
76b5cc776c9353a203cdde97e62b25f05d9633d14cfredc    public String getName() {
77b5cc776c9353a203cdde97e62b25f05d9633d14cfredc        return TAG;
7835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    }
7935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
8074ae04c73312403e89db0f8e9bd9601d403b4783fredc    public IProfileServiceBinder initBinder() {
8174ae04c73312403e89db0f8e9bd9601d403b4783fredc        return new BluetoothInputDeviceBinder(this);
8235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    }
8335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
84b5cc776c9353a203cdde97e62b25f05d9633d14cfredc    protected boolean start() {
856654f5c903de510a70f9e72cd5ad7837b615d93ffredc        mInputDevices = Collections.synchronizedMap(new HashMap<BluetoothDevice, Integer>());
866654f5c903de510a70f9e72cd5ad7837b615d93ffredc        initializeNative();
8774ae04c73312403e89db0f8e9bd9601d403b4783fredc        mNativeAvailable=true;
884f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        setHidService(this);
89b5cc776c9353a203cdde97e62b25f05d9633d14cfredc        return true;
906654f5c903de510a70f9e72cd5ad7837b615d93ffredc    }
916654f5c903de510a70f9e72cd5ad7837b615d93ffredc
92b5cc776c9353a203cdde97e62b25f05d9633d14cfredc    protected boolean stop() {
9335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        if (DBG) log("Stopping Bluetooth HidService");
9474ae04c73312403e89db0f8e9bd9601d403b4783fredc        return true;
9574ae04c73312403e89db0f8e9bd9601d403b4783fredc    }
9674ae04c73312403e89db0f8e9bd9601d403b4783fredc
9774ae04c73312403e89db0f8e9bd9601d403b4783fredc    protected boolean cleanup() {
9874ae04c73312403e89db0f8e9bd9601d403b4783fredc        if (mNativeAvailable) {
9974ae04c73312403e89db0f8e9bd9601d403b4783fredc            cleanupNative();
10074ae04c73312403e89db0f8e9bd9601d403b4783fredc            mNativeAvailable=false;
10174ae04c73312403e89db0f8e9bd9601d403b4783fredc        }
1026654f5c903de510a70f9e72cd5ad7837b615d93ffredc
103b5cc776c9353a203cdde97e62b25f05d9633d14cfredc        if(mInputDevices != null) {
104b5cc776c9353a203cdde97e62b25f05d9633d14cfredc            mInputDevices.clear();
1056654f5c903de510a70f9e72cd5ad7837b615d93ffredc        }
1064f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        clearHidService();
107b5cc776c9353a203cdde97e62b25f05d9633d14cfredc        return true;
10835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    }
10935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
1104f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    public static synchronized HidService getHidService(){
1114f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if (sHidService != null && sHidService.isAvailable()) {
1124f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            if (DBG) Log.d(TAG, "getHidService(): returning " + sHidService);
1134f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            return sHidService;
1144f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        }
1154f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if (DBG)  {
1164f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            if (sHidService == null) {
1174f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                Log.d(TAG, "getHidService(): service is NULL");
1184f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            } else if (!(sHidService.isAvailable())) {
1194f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                Log.d(TAG,"getHidService(): service is not available");
1204f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            }
1214f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        }
1224f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        return null;
1234f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    }
1244f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
1254f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    private static synchronized void setHidService(HidService instance) {
1264f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if (instance != null && instance.isAvailable()) {
1274f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            if (DBG) Log.d(TAG, "setHidService(): set to: " + sHidService);
1284f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            sHidService = instance;
1294f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        } else {
1304f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            if (DBG)  {
1314f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                if (sHidService == null) {
1324f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                    Log.d(TAG, "setHidService(): service not available");
1334f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                } else if (!sHidService.isAvailable()) {
1344f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                    Log.d(TAG,"setHidService(): service is cleaning up");
1354f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                }
1364f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            }
1374f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        }
1384f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    }
1394f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
1404f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    private static synchronized void clearHidService() {
1414f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        sHidService = null;
1424f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    }
1434f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
1444f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
14535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    private final Handler mHandler = new Handler() {
14635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
14735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        @Override
14835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        public void handleMessage(Message msg) {
14935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie            switch (msg.what) {
15035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                case MESSAGE_CONNECT:
15135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                {
15235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                    BluetoothDevice device = (BluetoothDevice) msg.obj;
15374ae04c73312403e89db0f8e9bd9601d403b4783fredc                    if (!connectHidNative(Utils.getByteAddress(device)) ) {
15435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                        broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTING);
15535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                        broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED);
15635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                        break;
15735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                    }
158ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta                    mTargetDevice = device;
15935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                }
16035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                    break;
16135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                case MESSAGE_DISCONNECT:
16235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                {
16335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                    BluetoothDevice device = (BluetoothDevice) msg.obj;
16474ae04c73312403e89db0f8e9bd9601d403b4783fredc                    if (!disconnectHidNative(Utils.getByteAddress(device)) ) {
16535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                        broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTING);
16635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                        broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED);
16735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                        break;
16835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                    }
16935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                }
17035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                    break;
17135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                case MESSAGE_CONNECT_STATE_CHANGED:
17235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                {
17335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                    BluetoothDevice device = getDevice((byte[]) msg.obj);
17435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                    int halState = msg.arg1;
17599a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M                    Integer prevStateInteger = mInputDevices.get(device);
17699a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M                    int prevState = (prevStateInteger == null) ?
17799a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M                        BluetoothInputDevice.STATE_DISCONNECTED :prevStateInteger;
17899a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M                    if(DBG) Log.d(TAG, "MESSAGE_CONNECT_STATE_CHANGED newState:"+
17999a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M                        convertHalState(halState)+", prevState:"+prevState);
180ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta                    if(halState == CONN_STATE_CONNECTED &&
181ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta                       prevState == BluetoothInputDevice.STATE_DISCONNECTED &&
182ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta                       (!okToConnect(device))) {
1830f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie                        if (DBG) Log.d(TAG,"Incoming HID connection rejected");
18499a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M                        disconnectHidNative(Utils.getByteAddress(device));
18599a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M                    } else {
18699a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M                        broadcastConnectionState(device, convertHalState(halState));
18799a6ee18f09cf8e7ddff91d68267db21867b3cdfSyed Ibrahim M                    }
188fe19c7f20ca3abc252965be60727e8a198cc6ff3Matthew Xie                    if (halState == CONN_STATE_CONNECTED &&
189fe19c7f20ca3abc252965be60727e8a198cc6ff3Matthew Xie                        (mTargetDevice != null && mTargetDevice.equals(device))) {
190ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta                        mTargetDevice = null;
191fe19c7f20ca3abc252965be60727e8a198cc6ff3Matthew Xie                        // local device originated connection to hid device, move out
192fe19c7f20ca3abc252965be60727e8a198cc6ff3Matthew Xie                        // of quiet mode
193fe19c7f20ca3abc252965be60727e8a198cc6ff3Matthew Xie                        AdapterService adapterService = AdapterService.getAdapterService();
194fe19c7f20ca3abc252965be60727e8a198cc6ff3Matthew Xie                        adapterService.enable(false);
195ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta                    }
19635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                }
19735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                    break;
19857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                case MESSAGE_GET_PROTOCOL_MODE:
19957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                {
20057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    BluetoothDevice device = (BluetoothDevice) msg.obj;
20174ae04c73312403e89db0f8e9bd9601d403b4783fredc                    if(!getProtocolModeNative(Utils.getByteAddress(device)) ) {
20257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                        Log.e(TAG, "Error: get protocol mode native returns false");
20357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    }
20457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                }
20557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                break;
20657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera
20757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                case MESSAGE_ON_GET_PROTOCOL_MODE:
20857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                {
20957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    BluetoothDevice device = getDevice((byte[]) msg.obj);
21057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    int protocolMode = msg.arg1;
21157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    broadcastProtocolMode(device, protocolMode);
21257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                }
21357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                break;
21457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                case MESSAGE_VIRTUAL_UNPLUG:
21557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                {
21657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    BluetoothDevice device = (BluetoothDevice) msg.obj;
21774ae04c73312403e89db0f8e9bd9601d403b4783fredc                    if(!virtualUnPlugNative(Utils.getByteAddress(device))) {
21857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                        Log.e(TAG, "Error: virtual unplug native returns false");
21957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    }
22057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                }
22157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                break;
22257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                case MESSAGE_SET_PROTOCOL_MODE:
22357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                {
22457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    BluetoothDevice device = (BluetoothDevice) msg.obj;
22557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    byte protocolMode = (byte) msg.arg1;
22657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    log("sending set protocol mode(" + protocolMode + ")");
22774ae04c73312403e89db0f8e9bd9601d403b4783fredc                    if(!setProtocolModeNative(Utils.getByteAddress(device), protocolMode)) {
22857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                        Log.e(TAG, "Error: set protocol mode native returns false");
22957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    }
23057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                }
23157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                break;
23257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                case MESSAGE_GET_REPORT:
23357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                {
23457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    BluetoothDevice device = (BluetoothDevice) msg.obj;
23557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    Bundle data = msg.getData();
23657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    byte reportType = data.getByte(BluetoothInputDevice.EXTRA_REPORT_TYPE);
23757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    byte reportId = data.getByte(BluetoothInputDevice.EXTRA_REPORT_ID);
23857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    int bufferSize = data.getInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE);
23974ae04c73312403e89db0f8e9bd9601d403b4783fredc                    if(!getReportNative(Utils.getByteAddress(device), reportType, reportId, bufferSize)) {
24057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                        Log.e(TAG, "Error: get report native returns false");
24157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    }
24257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                }
24357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                break;
244b8e4250de151551d5dacca895e62761355839d7dMike J. Chen                case MESSAGE_ON_GET_REPORT:
245b8e4250de151551d5dacca895e62761355839d7dMike J. Chen                {
246b8e4250de151551d5dacca895e62761355839d7dMike J. Chen                    BluetoothDevice device = getDevice((byte[])msg.obj);
247b8e4250de151551d5dacca895e62761355839d7dMike J. Chen                    Bundle data = msg.getData();
248b8e4250de151551d5dacca895e62761355839d7dMike J. Chen                    byte[] report = data.getByteArray(BluetoothInputDevice.EXTRA_REPORT);
249b8e4250de151551d5dacca895e62761355839d7dMike J. Chen                    int bufferSize = data.getInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE);
250b8e4250de151551d5dacca895e62761355839d7dMike J. Chen                    broadcastReport(device, report, bufferSize);
251b8e4250de151551d5dacca895e62761355839d7dMike J. Chen                }
252b8e4250de151551d5dacca895e62761355839d7dMike J. Chen                break;
2533a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen                case MESSAGE_ON_HANDSHAKE:
2543a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen                {
2553a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen                    BluetoothDevice device = getDevice((byte[])msg.obj);
2563a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen                    int status = msg.arg1;
2573a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen                    broadcastHandshake(device, status);
2583a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen                }
2593a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen                break;
26057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                case MESSAGE_SET_REPORT:
26157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                {
26257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    BluetoothDevice device = (BluetoothDevice) msg.obj;
26357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    Bundle data = msg.getData();
26457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    byte reportType = data.getByte(BluetoothInputDevice.EXTRA_REPORT_TYPE);
26557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    String report = data.getString(BluetoothInputDevice.EXTRA_REPORT);
26674ae04c73312403e89db0f8e9bd9601d403b4783fredc                    if(!setReportNative(Utils.getByteAddress(device), reportType, report)) {
26757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                        Log.e(TAG, "Error: set report native returns false");
26857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    }
26957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                }
27057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                break;
27157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                case MESSAGE_SEND_DATA:
27257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                {
27357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    BluetoothDevice device = (BluetoothDevice) msg.obj;
27457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    Bundle data = msg.getData();
27557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    String report = data.getString(BluetoothInputDevice.EXTRA_REPORT);
27674ae04c73312403e89db0f8e9bd9601d403b4783fredc                    if(!sendDataNative(Utils.getByteAddress(device), report)) {
27757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                        Log.e(TAG, "Error: send data native returns false");
27857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    }
27957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                }
28057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                break;
28157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                case MESSAGE_ON_VIRTUAL_UNPLUG:
28257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                {
28357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    BluetoothDevice device = getDevice((byte[]) msg.obj);
28457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    int status = msg.arg1;
28557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                    broadcastVirtualUnplugStatus(device, status);
28657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                }
28757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera                break;
28835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie            }
28935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        }
29035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    };
29135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
29235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    /**
29335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie     * Handlers for incoming service calls
29435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie     */
29574ae04c73312403e89db0f8e9bd9601d403b4783fredc    private static class BluetoothInputDeviceBinder extends IBluetoothInputDevice.Stub implements IProfileServiceBinder{
29674ae04c73312403e89db0f8e9bd9601d403b4783fredc        private HidService mService;
29774ae04c73312403e89db0f8e9bd9601d403b4783fredc        public BluetoothInputDeviceBinder(HidService svc) {
29874ae04c73312403e89db0f8e9bd9601d403b4783fredc            mService = svc;
29974ae04c73312403e89db0f8e9bd9601d403b4783fredc        }
30035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
30174ae04c73312403e89db0f8e9bd9601d403b4783fredc        public boolean cleanup() {
30274ae04c73312403e89db0f8e9bd9601d403b4783fredc            mService = null;
30335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie            return true;
30435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        }
30535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
30674ae04c73312403e89db0f8e9bd9601d403b4783fredc        private HidService getService() {
30737510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            if (!Utils.checkCaller()) {
30837510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu                Log.w(TAG,"InputDevice call not allowed for non-active user");
30937510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu                return null;
31037510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            }
31137510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu
31274ae04c73312403e89db0f8e9bd9601d403b4783fredc            if (mService  != null && mService.isAvailable()) {
31374ae04c73312403e89db0f8e9bd9601d403b4783fredc                return mService;
31474ae04c73312403e89db0f8e9bd9601d403b4783fredc            }
31574ae04c73312403e89db0f8e9bd9601d403b4783fredc            return null;
31674ae04c73312403e89db0f8e9bd9601d403b4783fredc        }
31774ae04c73312403e89db0f8e9bd9601d403b4783fredc
31874ae04c73312403e89db0f8e9bd9601d403b4783fredc        public boolean connect(BluetoothDevice device) {
31974ae04c73312403e89db0f8e9bd9601d403b4783fredc            HidService service = getService();
32074ae04c73312403e89db0f8e9bd9601d403b4783fredc            if (service == null) return false;
32174ae04c73312403e89db0f8e9bd9601d403b4783fredc            return service.connect(device);
32274ae04c73312403e89db0f8e9bd9601d403b4783fredc        }
32374ae04c73312403e89db0f8e9bd9601d403b4783fredc
32435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        public boolean disconnect(BluetoothDevice device) {
32574ae04c73312403e89db0f8e9bd9601d403b4783fredc            HidService service = getService();
32674ae04c73312403e89db0f8e9bd9601d403b4783fredc            if (service == null) return false;
32774ae04c73312403e89db0f8e9bd9601d403b4783fredc            return service.disconnect(device);
32835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        }
32935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
33035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        public int getConnectionState(BluetoothDevice device) {
33174ae04c73312403e89db0f8e9bd9601d403b4783fredc            HidService service = getService();
33274ae04c73312403e89db0f8e9bd9601d403b4783fredc            if (service == null) return BluetoothInputDevice.STATE_DISCONNECTED;
33374ae04c73312403e89db0f8e9bd9601d403b4783fredc            return service.getConnectionState(device);
33435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        }
33535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
33635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        public List<BluetoothDevice> getConnectedDevices() {
33774ae04c73312403e89db0f8e9bd9601d403b4783fredc            return getDevicesMatchingConnectionStates(
33835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                    new int[] {BluetoothProfile.STATE_CONNECTED});
33935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        }
34035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
34135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
34274ae04c73312403e89db0f8e9bd9601d403b4783fredc            HidService service = getService();
34374ae04c73312403e89db0f8e9bd9601d403b4783fredc            if (service == null) return new ArrayList<BluetoothDevice>(0);
34474ae04c73312403e89db0f8e9bd9601d403b4783fredc            return service.getDevicesMatchingConnectionStates(states);
34535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        }
34635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
34735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        public boolean setPriority(BluetoothDevice device, int priority) {
34874ae04c73312403e89db0f8e9bd9601d403b4783fredc            HidService service = getService();
34974ae04c73312403e89db0f8e9bd9601d403b4783fredc            if (service == null) return false;
35074ae04c73312403e89db0f8e9bd9601d403b4783fredc            return service.setPriority(device, priority);
35135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        }
35235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
35335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        public int getPriority(BluetoothDevice device) {
35474ae04c73312403e89db0f8e9bd9601d403b4783fredc            HidService service = getService();
35574ae04c73312403e89db0f8e9bd9601d403b4783fredc            if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED;
35674ae04c73312403e89db0f8e9bd9601d403b4783fredc            return service.getPriority(device);
35735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        }
35874ae04c73312403e89db0f8e9bd9601d403b4783fredc
3591404ab28fd296373a98b766b0b01193985446eabHarish Paryani        /* The following APIs regarding test app for compliance */
36057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        public boolean getProtocolMode(BluetoothDevice device) {
36174ae04c73312403e89db0f8e9bd9601d403b4783fredc            HidService service = getService();
36274ae04c73312403e89db0f8e9bd9601d403b4783fredc            if (service == null) return false;
36374ae04c73312403e89db0f8e9bd9601d403b4783fredc            return service.getProtocolMode(device);
36457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        }
36557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera
36657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        public boolean virtualUnplug(BluetoothDevice device) {
36774ae04c73312403e89db0f8e9bd9601d403b4783fredc            HidService service = getService();
36874ae04c73312403e89db0f8e9bd9601d403b4783fredc            if (service == null) return false;
36974ae04c73312403e89db0f8e9bd9601d403b4783fredc            return service.virtualUnplug(device);
37057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        }
37157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera
37257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
37374ae04c73312403e89db0f8e9bd9601d403b4783fredc            HidService service = getService();
37474ae04c73312403e89db0f8e9bd9601d403b4783fredc            if (service == null) return false;
37574ae04c73312403e89db0f8e9bd9601d403b4783fredc            return service.setProtocolMode(device, protocolMode);
37657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        }
37774ae04c73312403e89db0f8e9bd9601d403b4783fredc
37857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) {
37974ae04c73312403e89db0f8e9bd9601d403b4783fredc            HidService service = getService();
38074ae04c73312403e89db0f8e9bd9601d403b4783fredc            if (service == null) return false;
38174ae04c73312403e89db0f8e9bd9601d403b4783fredc            return service.getReport(device, reportType, reportId, bufferSize) ;
38257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        }
38357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera
38457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        public boolean setReport(BluetoothDevice device, byte reportType, String report) {
38574ae04c73312403e89db0f8e9bd9601d403b4783fredc            HidService service = getService();
38674ae04c73312403e89db0f8e9bd9601d403b4783fredc            if (service == null) return false;
38774ae04c73312403e89db0f8e9bd9601d403b4783fredc            return service.setReport(device, reportType, report);
38857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        }
38957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera
39057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        public boolean sendData(BluetoothDevice device, String report) {
39174ae04c73312403e89db0f8e9bd9601d403b4783fredc            HidService service = getService();
39274ae04c73312403e89db0f8e9bd9601d403b4783fredc            if (service == null) return false;
39374ae04c73312403e89db0f8e9bd9601d403b4783fredc            return service.sendData(device, report);
39474ae04c73312403e89db0f8e9bd9601d403b4783fredc        }
39574ae04c73312403e89db0f8e9bd9601d403b4783fredc    };
39674ae04c73312403e89db0f8e9bd9601d403b4783fredc
39774ae04c73312403e89db0f8e9bd9601d403b4783fredc    //APIs
39874ae04c73312403e89db0f8e9bd9601d403b4783fredc    boolean connect(BluetoothDevice device) {
39974ae04c73312403e89db0f8e9bd9601d403b4783fredc        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
40074ae04c73312403e89db0f8e9bd9601d403b4783fredc        if (getConnectionState(device) != BluetoothInputDevice.STATE_DISCONNECTED) {
40174ae04c73312403e89db0f8e9bd9601d403b4783fredc            Log.e(TAG, "Hid Device not disconnected: " + device);
40274ae04c73312403e89db0f8e9bd9601d403b4783fredc            return false;
40374ae04c73312403e89db0f8e9bd9601d403b4783fredc        }
40474ae04c73312403e89db0f8e9bd9601d403b4783fredc        if (getPriority(device) == BluetoothInputDevice.PRIORITY_OFF) {
40574ae04c73312403e89db0f8e9bd9601d403b4783fredc            Log.e(TAG, "Hid Device PRIORITY_OFF: " + device);
40674ae04c73312403e89db0f8e9bd9601d403b4783fredc            return false;
40774ae04c73312403e89db0f8e9bd9601d403b4783fredc        }
40874ae04c73312403e89db0f8e9bd9601d403b4783fredc
40974ae04c73312403e89db0f8e9bd9601d403b4783fredc        Message msg = mHandler.obtainMessage(MESSAGE_CONNECT, device);
41074ae04c73312403e89db0f8e9bd9601d403b4783fredc        mHandler.sendMessage(msg);
41174ae04c73312403e89db0f8e9bd9601d403b4783fredc        return true;
41274ae04c73312403e89db0f8e9bd9601d403b4783fredc    }
41374ae04c73312403e89db0f8e9bd9601d403b4783fredc
41474ae04c73312403e89db0f8e9bd9601d403b4783fredc    boolean disconnect(BluetoothDevice device) {
41574ae04c73312403e89db0f8e9bd9601d403b4783fredc        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
41674ae04c73312403e89db0f8e9bd9601d403b4783fredc        Message msg = mHandler.obtainMessage(MESSAGE_DISCONNECT,device);
41774ae04c73312403e89db0f8e9bd9601d403b4783fredc        mHandler.sendMessage(msg);
41874ae04c73312403e89db0f8e9bd9601d403b4783fredc        return true;
41974ae04c73312403e89db0f8e9bd9601d403b4783fredc    }
42074ae04c73312403e89db0f8e9bd9601d403b4783fredc
42174ae04c73312403e89db0f8e9bd9601d403b4783fredc    int getConnectionState(BluetoothDevice device) {
42274ae04c73312403e89db0f8e9bd9601d403b4783fredc        if (mInputDevices.get(device) == null) {
42374ae04c73312403e89db0f8e9bd9601d403b4783fredc            return BluetoothInputDevice.STATE_DISCONNECTED;
42474ae04c73312403e89db0f8e9bd9601d403b4783fredc        }
42574ae04c73312403e89db0f8e9bd9601d403b4783fredc        return mInputDevices.get(device);
42674ae04c73312403e89db0f8e9bd9601d403b4783fredc    }
42774ae04c73312403e89db0f8e9bd9601d403b4783fredc
42874ae04c73312403e89db0f8e9bd9601d403b4783fredc    List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
42974ae04c73312403e89db0f8e9bd9601d403b4783fredc        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
43074ae04c73312403e89db0f8e9bd9601d403b4783fredc        List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>();
43174ae04c73312403e89db0f8e9bd9601d403b4783fredc
43274ae04c73312403e89db0f8e9bd9601d403b4783fredc        for (BluetoothDevice device: mInputDevices.keySet()) {
43374ae04c73312403e89db0f8e9bd9601d403b4783fredc            int inputDeviceState = getConnectionState(device);
43474ae04c73312403e89db0f8e9bd9601d403b4783fredc            for (int state : states) {
43574ae04c73312403e89db0f8e9bd9601d403b4783fredc                if (state == inputDeviceState) {
43674ae04c73312403e89db0f8e9bd9601d403b4783fredc                    inputDevices.add(device);
43774ae04c73312403e89db0f8e9bd9601d403b4783fredc                    break;
43874ae04c73312403e89db0f8e9bd9601d403b4783fredc                }
43957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera            }
44074ae04c73312403e89db0f8e9bd9601d403b4783fredc        }
44174ae04c73312403e89db0f8e9bd9601d403b4783fredc        return inputDevices;
44274ae04c73312403e89db0f8e9bd9601d403b4783fredc    }
44357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera
4444f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    public boolean setPriority(BluetoothDevice device, int priority) {
44574ae04c73312403e89db0f8e9bd9601d403b4783fredc        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
44674ae04c73312403e89db0f8e9bd9601d403b4783fredc                                       "Need BLUETOOTH_ADMIN permission");
447c7ead6d5827f3832b9210e92fab7597142059852Jeff Sharkey        Settings.Global.putInt(getContentResolver(),
448c7ead6d5827f3832b9210e92fab7597142059852Jeff Sharkey            Settings.Global.getBluetoothInputDevicePriorityKey(device.getAddress()),
44974ae04c73312403e89db0f8e9bd9601d403b4783fredc            priority);
45074ae04c73312403e89db0f8e9bd9601d403b4783fredc        if (DBG) Log.d(TAG,"Saved priority " + device + " = " + priority);
45174ae04c73312403e89db0f8e9bd9601d403b4783fredc        return true;
45274ae04c73312403e89db0f8e9bd9601d403b4783fredc    }
45374ae04c73312403e89db0f8e9bd9601d403b4783fredc
4544f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    public  int getPriority(BluetoothDevice device) {
45574ae04c73312403e89db0f8e9bd9601d403b4783fredc        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
45674ae04c73312403e89db0f8e9bd9601d403b4783fredc                                       "Need BLUETOOTH_ADMIN permission");
457c7ead6d5827f3832b9210e92fab7597142059852Jeff Sharkey        int priority = Settings.Global.getInt(getContentResolver(),
458c7ead6d5827f3832b9210e92fab7597142059852Jeff Sharkey            Settings.Global.getBluetoothInputDevicePriorityKey(device.getAddress()),
45974ae04c73312403e89db0f8e9bd9601d403b4783fredc            BluetoothProfile.PRIORITY_UNDEFINED);
46074ae04c73312403e89db0f8e9bd9601d403b4783fredc        return priority;
46174ae04c73312403e89db0f8e9bd9601d403b4783fredc    }
46274ae04c73312403e89db0f8e9bd9601d403b4783fredc
46374ae04c73312403e89db0f8e9bd9601d403b4783fredc    /* The following APIs regarding test app for compliance */
46474ae04c73312403e89db0f8e9bd9601d403b4783fredc    boolean getProtocolMode(BluetoothDevice device) {
46574ae04c73312403e89db0f8e9bd9601d403b4783fredc        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
46674ae04c73312403e89db0f8e9bd9601d403b4783fredc                                       "Need BLUETOOTH_ADMIN permission");
46774ae04c73312403e89db0f8e9bd9601d403b4783fredc        int state = this.getConnectionState(device);
46874ae04c73312403e89db0f8e9bd9601d403b4783fredc        if (state != BluetoothInputDevice.STATE_CONNECTED) {
46974ae04c73312403e89db0f8e9bd9601d403b4783fredc            return false;
47057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        }
47174ae04c73312403e89db0f8e9bd9601d403b4783fredc        Message msg = mHandler.obtainMessage(MESSAGE_GET_PROTOCOL_MODE,device);
47274ae04c73312403e89db0f8e9bd9601d403b4783fredc        mHandler.sendMessage(msg);
47374ae04c73312403e89db0f8e9bd9601d403b4783fredc        return true;
47474ae04c73312403e89db0f8e9bd9601d403b4783fredc        /* String objectPath = getObjectPathFromAddress(device.getAddress());
47574ae04c73312403e89db0f8e9bd9601d403b4783fredc            return getProtocolModeInputDeviceNative(objectPath);*/
47674ae04c73312403e89db0f8e9bd9601d403b4783fredc    }
47735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
47874ae04c73312403e89db0f8e9bd9601d403b4783fredc    boolean virtualUnplug(BluetoothDevice device) {
47974ae04c73312403e89db0f8e9bd9601d403b4783fredc        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
48074ae04c73312403e89db0f8e9bd9601d403b4783fredc                                       "Need BLUETOOTH_ADMIN permission");
48174ae04c73312403e89db0f8e9bd9601d403b4783fredc        int state = this.getConnectionState(device);
48274ae04c73312403e89db0f8e9bd9601d403b4783fredc        if (state != BluetoothInputDevice.STATE_CONNECTED) {
48374ae04c73312403e89db0f8e9bd9601d403b4783fredc            return false;
48474ae04c73312403e89db0f8e9bd9601d403b4783fredc        }
48574ae04c73312403e89db0f8e9bd9601d403b4783fredc        Message msg = mHandler.obtainMessage(MESSAGE_VIRTUAL_UNPLUG,device);
48674ae04c73312403e89db0f8e9bd9601d403b4783fredc        mHandler.sendMessage(msg);
48774ae04c73312403e89db0f8e9bd9601d403b4783fredc        return true;
48874ae04c73312403e89db0f8e9bd9601d403b4783fredc    }
48974ae04c73312403e89db0f8e9bd9601d403b4783fredc
49074ae04c73312403e89db0f8e9bd9601d403b4783fredc    boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
49174ae04c73312403e89db0f8e9bd9601d403b4783fredc        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
49274ae04c73312403e89db0f8e9bd9601d403b4783fredc                                       "Need BLUETOOTH_ADMIN permission");
49374ae04c73312403e89db0f8e9bd9601d403b4783fredc        int state = this.getConnectionState(device);
49474ae04c73312403e89db0f8e9bd9601d403b4783fredc        if (state != BluetoothInputDevice.STATE_CONNECTED) {
49574ae04c73312403e89db0f8e9bd9601d403b4783fredc            return false;
49674ae04c73312403e89db0f8e9bd9601d403b4783fredc        }
49774ae04c73312403e89db0f8e9bd9601d403b4783fredc        Message msg = mHandler.obtainMessage(MESSAGE_SET_PROTOCOL_MODE);
49874ae04c73312403e89db0f8e9bd9601d403b4783fredc        msg.obj = device;
49974ae04c73312403e89db0f8e9bd9601d403b4783fredc        msg.arg1 = protocolMode;
50074ae04c73312403e89db0f8e9bd9601d403b4783fredc        mHandler.sendMessage(msg);
50174ae04c73312403e89db0f8e9bd9601d403b4783fredc        return true ;
50274ae04c73312403e89db0f8e9bd9601d403b4783fredc    }
50374ae04c73312403e89db0f8e9bd9601d403b4783fredc
50474ae04c73312403e89db0f8e9bd9601d403b4783fredc    boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) {
50574ae04c73312403e89db0f8e9bd9601d403b4783fredc        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
50674ae04c73312403e89db0f8e9bd9601d403b4783fredc                                       "Need BLUETOOTH_ADMIN permission");
50774ae04c73312403e89db0f8e9bd9601d403b4783fredc        int state = this.getConnectionState(device);
50874ae04c73312403e89db0f8e9bd9601d403b4783fredc        if (state != BluetoothInputDevice.STATE_CONNECTED) {
50974ae04c73312403e89db0f8e9bd9601d403b4783fredc            return false;
51074ae04c73312403e89db0f8e9bd9601d403b4783fredc        }
51174ae04c73312403e89db0f8e9bd9601d403b4783fredc        Message msg = mHandler.obtainMessage(MESSAGE_GET_REPORT);
51274ae04c73312403e89db0f8e9bd9601d403b4783fredc        msg.obj = device;
51374ae04c73312403e89db0f8e9bd9601d403b4783fredc        Bundle data = new Bundle();
51474ae04c73312403e89db0f8e9bd9601d403b4783fredc        data.putByte(BluetoothInputDevice.EXTRA_REPORT_TYPE, reportType);
51574ae04c73312403e89db0f8e9bd9601d403b4783fredc        data.putByte(BluetoothInputDevice.EXTRA_REPORT_ID, reportId);
51674ae04c73312403e89db0f8e9bd9601d403b4783fredc        data.putInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE, bufferSize);
51774ae04c73312403e89db0f8e9bd9601d403b4783fredc        msg.setData(data);
51874ae04c73312403e89db0f8e9bd9601d403b4783fredc        mHandler.sendMessage(msg);
51974ae04c73312403e89db0f8e9bd9601d403b4783fredc        return true ;
52074ae04c73312403e89db0f8e9bd9601d403b4783fredc    }
52174ae04c73312403e89db0f8e9bd9601d403b4783fredc
52274ae04c73312403e89db0f8e9bd9601d403b4783fredc    boolean setReport(BluetoothDevice device, byte reportType, String report) {
52374ae04c73312403e89db0f8e9bd9601d403b4783fredc        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
52474ae04c73312403e89db0f8e9bd9601d403b4783fredc                                                   "Need BLUETOOTH_ADMIN permission");
52574ae04c73312403e89db0f8e9bd9601d403b4783fredc        int state = this.getConnectionState(device);
52674ae04c73312403e89db0f8e9bd9601d403b4783fredc        if (state != BluetoothInputDevice.STATE_CONNECTED) {
52774ae04c73312403e89db0f8e9bd9601d403b4783fredc            return false;
52874ae04c73312403e89db0f8e9bd9601d403b4783fredc        }
52974ae04c73312403e89db0f8e9bd9601d403b4783fredc        Message msg = mHandler.obtainMessage(MESSAGE_SET_REPORT);
53074ae04c73312403e89db0f8e9bd9601d403b4783fredc        msg.obj = device;
53174ae04c73312403e89db0f8e9bd9601d403b4783fredc        Bundle data = new Bundle();
53274ae04c73312403e89db0f8e9bd9601d403b4783fredc        data.putByte(BluetoothInputDevice.EXTRA_REPORT_TYPE, reportType);
53374ae04c73312403e89db0f8e9bd9601d403b4783fredc        data.putString(BluetoothInputDevice.EXTRA_REPORT, report);
53474ae04c73312403e89db0f8e9bd9601d403b4783fredc        msg.setData(data);
53574ae04c73312403e89db0f8e9bd9601d403b4783fredc        mHandler.sendMessage(msg);
53674ae04c73312403e89db0f8e9bd9601d403b4783fredc        return true ;
53774ae04c73312403e89db0f8e9bd9601d403b4783fredc
53874ae04c73312403e89db0f8e9bd9601d403b4783fredc    }
53974ae04c73312403e89db0f8e9bd9601d403b4783fredc
54074ae04c73312403e89db0f8e9bd9601d403b4783fredc    boolean sendData(BluetoothDevice device, String report) {
54174ae04c73312403e89db0f8e9bd9601d403b4783fredc        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
54274ae04c73312403e89db0f8e9bd9601d403b4783fredc                                                   "Need BLUETOOTH_ADMIN permission");
54374ae04c73312403e89db0f8e9bd9601d403b4783fredc        int state = this.getConnectionState(device);
54474ae04c73312403e89db0f8e9bd9601d403b4783fredc        if (state != BluetoothInputDevice.STATE_CONNECTED) {
54574ae04c73312403e89db0f8e9bd9601d403b4783fredc            return false;
54674ae04c73312403e89db0f8e9bd9601d403b4783fredc        }
54774ae04c73312403e89db0f8e9bd9601d403b4783fredc
54874ae04c73312403e89db0f8e9bd9601d403b4783fredc        return sendDataNative(Utils.getByteAddress(device), report);
54974ae04c73312403e89db0f8e9bd9601d403b4783fredc        /*Message msg = mHandler.obtainMessage(MESSAGE_SEND_DATA);
55074ae04c73312403e89db0f8e9bd9601d403b4783fredc        msg.obj = device;
55174ae04c73312403e89db0f8e9bd9601d403b4783fredc        Bundle data = new Bundle();
55274ae04c73312403e89db0f8e9bd9601d403b4783fredc        data.putString(BluetoothInputDevice.EXTRA_REPORT, report);
55374ae04c73312403e89db0f8e9bd9601d403b4783fredc        msg.setData(data);
55474ae04c73312403e89db0f8e9bd9601d403b4783fredc        mHandler.sendMessage(msg);
55574ae04c73312403e89db0f8e9bd9601d403b4783fredc        return true ;*/
55674ae04c73312403e89db0f8e9bd9601d403b4783fredc    }
55774ae04c73312403e89db0f8e9bd9601d403b4783fredc
55857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera    private void onGetProtocolMode(byte[] address, int mode) {
55957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        Message msg = mHandler.obtainMessage(MESSAGE_ON_GET_PROTOCOL_MODE);
56057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        msg.obj = address;
56157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        msg.arg1 = mode;
56257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        mHandler.sendMessage(msg);
56357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera    }
56457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera
565b8e4250de151551d5dacca895e62761355839d7dMike J. Chen    private void onGetReport(byte[] address, byte[] report, int rpt_size) {
566b8e4250de151551d5dacca895e62761355839d7dMike J. Chen        Message msg = mHandler.obtainMessage(MESSAGE_ON_GET_REPORT);
567b8e4250de151551d5dacca895e62761355839d7dMike J. Chen        msg.obj = address;
568b8e4250de151551d5dacca895e62761355839d7dMike J. Chen        Bundle data = new Bundle();
569b8e4250de151551d5dacca895e62761355839d7dMike J. Chen        data.putByteArray(BluetoothInputDevice.EXTRA_REPORT, report);
570b8e4250de151551d5dacca895e62761355839d7dMike J. Chen        data.putInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE, rpt_size);
571b8e4250de151551d5dacca895e62761355839d7dMike J. Chen        msg.setData(data);
572b8e4250de151551d5dacca895e62761355839d7dMike J. Chen        mHandler.sendMessage(msg);
573b8e4250de151551d5dacca895e62761355839d7dMike J. Chen    }
574b8e4250de151551d5dacca895e62761355839d7dMike J. Chen
5753a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen    private void onHandshake(byte[] address, int status) {
5763a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen        Message msg = mHandler.obtainMessage(MESSAGE_ON_HANDSHAKE);
5773a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen        msg.obj = address;
5783a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen        msg.arg1 = status;
5793a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen        mHandler.sendMessage(msg);
5803a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen    }
5813a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen
58257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera    private void onVirtualUnplug(byte[] address, int status) {
58357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        Message msg = mHandler.obtainMessage(MESSAGE_ON_VIRTUAL_UNPLUG);
58457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        msg.obj = address;
58557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        msg.arg1 = status;
58657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        mHandler.sendMessage(msg);
58757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera    }
58857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera
58935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    private void onConnectStateChanged(byte[] address, int state) {
59035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        Message msg = mHandler.obtainMessage(MESSAGE_CONNECT_STATE_CHANGED);
59135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        msg.obj = address;
59235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        msg.arg1 = state;
59335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        mHandler.sendMessage(msg);
59435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    }
59535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
59635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    // This method does not check for error conditon (newState == prevState)
59735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    private void broadcastConnectionState(BluetoothDevice device, int newState) {
59835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        Integer prevStateInteger = mInputDevices.get(device);
59935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        int prevState = (prevStateInteger == null) ? BluetoothInputDevice.STATE_DISCONNECTED :
60035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                                                     prevStateInteger;
60135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        if (prevState == newState) {
60235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie            Log.w(TAG, "no state change: " + newState);
60335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie            return;
60435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        }
60535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        mInputDevices.put(device, newState);
60635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
607a25e9c65c2a0192b7b3d819e2b87704f1942aa2fSreenidhi T        /* Notifying the connection state change of the profile before sending the intent for
608a25e9c65c2a0192b7b3d819e2b87704f1942aa2fSreenidhi T           connection state change, as it was causing a race condition, with the UI not being
609a25e9c65c2a0192b7b3d819e2b87704f1942aa2fSreenidhi T           updated with the correct connection state. */
610fd1da115cbf09b7dd9bca3c7d3a4fb816a835dc5Matthew Xie        log("Connection state " + device + ": " + prevState + "->" + newState);
611a25e9c65c2a0192b7b3d819e2b87704f1942aa2fSreenidhi T        notifyProfileConnectionStateChanged(device, BluetoothProfile.INPUT_DEVICE,
612a25e9c65c2a0192b7b3d819e2b87704f1942aa2fSreenidhi T                                            newState, prevState);
61335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        Intent intent = new Intent(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
61435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
61535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        intent.putExtra(BluetoothProfile.EXTRA_STATE, newState);
61635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
61735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
61835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        sendBroadcast(intent, BLUETOOTH_PERM);
61935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    }
62035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
6213a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen    private void broadcastHandshake(BluetoothDevice device, int status) {
6223a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen        Intent intent = new Intent(BluetoothInputDevice.ACTION_HANDSHAKE);
6233a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
6243a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen        intent.putExtra(BluetoothInputDevice.EXTRA_STATUS, status);
6253a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
6263a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen        sendBroadcast(intent, BLUETOOTH_PERM);
6273a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen    }
6283a04c35ba5f723ee4a6e1f1c37514691ebd1447dMike J. Chen
62957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera    private void broadcastProtocolMode(BluetoothDevice device, int protocolMode) {
63057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        Intent intent = new Intent(BluetoothInputDevice.ACTION_PROTOCOL_MODE_CHANGED);
63157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
63257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        intent.putExtra(BluetoothInputDevice.EXTRA_PROTOCOL_MODE, protocolMode);
63357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
63457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        sendBroadcast(intent, BLUETOOTH_PERM);
63557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        if (DBG) log("Protocol Mode (" + device + "): " + protocolMode);
63657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera    }
63757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera
638b8e4250de151551d5dacca895e62761355839d7dMike J. Chen    private void broadcastReport(BluetoothDevice device, byte[] report, int rpt_size) {
639b8e4250de151551d5dacca895e62761355839d7dMike J. Chen        Intent intent = new Intent(BluetoothInputDevice.ACTION_REPORT);
640b8e4250de151551d5dacca895e62761355839d7dMike J. Chen        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
641b8e4250de151551d5dacca895e62761355839d7dMike J. Chen        intent.putExtra(BluetoothInputDevice.EXTRA_REPORT, report);
642b8e4250de151551d5dacca895e62761355839d7dMike J. Chen        intent.putExtra(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE, rpt_size);
643b8e4250de151551d5dacca895e62761355839d7dMike J. Chen        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
644b8e4250de151551d5dacca895e62761355839d7dMike J. Chen        sendBroadcast(intent, BLUETOOTH_PERM);
645b8e4250de151551d5dacca895e62761355839d7dMike J. Chen    }
646b8e4250de151551d5dacca895e62761355839d7dMike J. Chen
64757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera    private void broadcastVirtualUnplugStatus(BluetoothDevice device, int status) {
64857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        Intent intent = new Intent(BluetoothInputDevice.ACTION_VIRTUAL_UNPLUG_STATUS);
64957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
65057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        intent.putExtra(BluetoothInputDevice.EXTRA_VIRTUAL_UNPLUG_STATUS, status);
65157addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
65257addccaa75691f8eb6f35204d608a63695a9705Priti Aghera        sendBroadcast(intent, BLUETOOTH_PERM);
65357addccaa75691f8eb6f35204d608a63695a9705Priti Aghera    }
65457addccaa75691f8eb6f35204d608a63695a9705Priti Aghera
655ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta    private boolean okToConnect(BluetoothDevice device) {
656ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta        AdapterService adapterService = AdapterService.getAdapterService();
657ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta        //check if it is inbound connection in Quiet mode, priority and Bond status
658ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta        //to decide if its ok to allow this connection
659ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta        if((adapterService == null)||
660ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta           ((adapterService.isQuietModeEnabled()) &&(mTargetDevice == null)) ||
661ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta           (BluetoothProfile.PRIORITY_OFF == getPriority(device)) ||
662ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta           (device.getBondState() == BluetoothDevice.BOND_NONE))
663ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta            return false;
664ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta
665ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta        return true;
666ca6110d57998fee7c7b572ca29061ee99a82ba37Ganesh Ganapathi Batta    }
66774ae04c73312403e89db0f8e9bd9601d403b4783fredc    private static int convertHalState(int halState) {
66835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        switch (halState) {
66935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie            case CONN_STATE_CONNECTED:
67035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                return BluetoothProfile.STATE_CONNECTED;
67135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie            case CONN_STATE_CONNECTING:
67235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                return BluetoothProfile.STATE_CONNECTING;
67335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie            case CONN_STATE_DISCONNECTED:
67435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                return BluetoothProfile.STATE_DISCONNECTED;
67535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie            case CONN_STATE_DISCONNECTING:
67635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                return BluetoothProfile.STATE_DISCONNECTING;
67735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie            default:
67835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                Log.e(TAG, "bad hid connection state: " + halState);
67935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie                return BluetoothProfile.STATE_DISCONNECTED;
68035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie        }
68135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    }
68235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
68335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    // Constants matching Hal header file bt_hh.h
68435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    // bthh_connection_state_t
68535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    private final static int CONN_STATE_CONNECTED = 0;
68635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    private final static int CONN_STATE_CONNECTING = 1;
68735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    private final static int CONN_STATE_DISCONNECTED = 2;
68835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    private final static int CONN_STATE_DISCONNECTING = 3;
68935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
69035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    private native static void classInitNative();
6916654f5c903de510a70f9e72cd5ad7837b615d93ffredc    private native void initializeNative();
6926654f5c903de510a70f9e72cd5ad7837b615d93ffredc    private native void cleanupNative();
69335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    private native boolean connectHidNative(byte[] btAddress);
69435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie    private native boolean disconnectHidNative(byte[] btAddress);
69557addccaa75691f8eb6f35204d608a63695a9705Priti Aghera    private native boolean getProtocolModeNative(byte[] btAddress);
69657addccaa75691f8eb6f35204d608a63695a9705Priti Aghera    private native boolean virtualUnPlugNative(byte[] btAddress);
69757addccaa75691f8eb6f35204d608a63695a9705Priti Aghera    private native boolean setProtocolModeNative(byte[] btAddress, byte protocolMode);
69857addccaa75691f8eb6f35204d608a63695a9705Priti Aghera    private native boolean getReportNative(byte[]btAddress, byte reportType, byte reportId, int bufferSize);
69957addccaa75691f8eb6f35204d608a63695a9705Priti Aghera    private native boolean setReportNative(byte[] btAddress, byte reportType, String report);
70057addccaa75691f8eb6f35204d608a63695a9705Priti Aghera    private native boolean sendDataNative(byte[] btAddress, String report);
70135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie}
702