1e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta/*
2e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta * Copyright (C) 2016 The Android Open Source Project
3e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta *
4e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta * Licensed under the Apache License, Version 2.0 (the "License");
5e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta * you may not use this file except in compliance with the License.
6e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta * You may obtain a copy of the License at
7e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta *
8e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta *      http://www.apache.org/licenses/LICENSE-2.0
9e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta *
10e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta * Unless required by applicable law or agreed to in writing, software
11e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta * distributed under the License is distributed on an "AS IS" BASIS,
12e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta * See the License for the specific language governing permissions and
14e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta * limitations under the License.
15e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta */
16e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
17e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Guptapackage android.bluetooth;
18e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
190afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogovimport android.annotation.SdkConstant;
200afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogovimport android.annotation.SdkConstant.SdkConstantType;
21e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Guptaimport android.content.ComponentName;
22e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Guptaimport android.content.Context;
23e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Guptaimport android.content.Intent;
24e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Guptaimport android.content.ServiceConnection;
25e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Guptaimport android.os.IBinder;
26e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Guptaimport android.os.RemoteException;
27e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Guptaimport android.util.Log;
28e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
29dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogovimport java.util.ArrayList;
300146463d70355592da85c3605aaaef4cf0b7335eJack Heimport java.util.Arrays;
31e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Guptaimport java.util.List;
32e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
33e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta/**
34e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta * @hide
35e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta */
360afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogovpublic final class BluetoothInputHost implements BluetoothProfile {
37e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
380afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov    private static final String TAG = BluetoothInputHost.class.getSimpleName();
39e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
400afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov    /**
410afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     * Intent used to broadcast the change in connection state of the Input
420afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     * Host profile.
430afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     *
440afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     * <p>This intent will have 3 extras:
450afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     * <ul>
460afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     *   <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
470afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     *   <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
480afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
490afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     * </ul>
500afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     *
510afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
520afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
530afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
540afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     *
550afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
560afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     * receive.
570afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov     */
580afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
59e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final String ACTION_CONNECTION_STATE_CHANGED =
600afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov        "android.bluetooth.inputhost.profile.action.CONNECTION_STATE_CHANGED";
61e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
62e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
63e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Constants representing device subclass.
64e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
65e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @see #registerApp(String, String, String, byte, byte[],
66e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *      BluetoothHidDeviceCallback)
67e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
68e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte SUBCLASS1_NONE = (byte) 0x00;
69e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte SUBCLASS1_KEYBOARD = (byte) 0x40;
70e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte SUBCLASS1_MOUSE = (byte) 0x80;
71e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte SUBCLASS1_COMBO = (byte) 0xC0;
72e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
73e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte SUBCLASS2_UNCATEGORIZED = (byte) 0x00;
74e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte SUBCLASS2_JOYSTICK = (byte) 0x01;
75e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte SUBCLASS2_GAMEPAD = (byte) 0x02;
76e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte SUBCLASS2_REMOTE_CONTROL = (byte) 0x03;
77e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte SUBCLASS2_SENSING_DEVICE = (byte) 0x04;
78e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte SUBCLASS2_DIGITIZER_TABLED = (byte) 0x05;
79e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte SUBCLASS2_CARD_READER = (byte) 0x06;
80e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
81e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
82e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Constants representing report types.
83e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
84e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @see BluetoothHidDeviceCallback#onGetReport(byte, byte, int)
85e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @see BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[])
86e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @see BluetoothHidDeviceCallback#onIntrData(byte, byte[])
87e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
88e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte REPORT_TYPE_INPUT = (byte) 1;
89e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte REPORT_TYPE_OUTPUT = (byte) 2;
90e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte REPORT_TYPE_FEATURE = (byte) 3;
91e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
92e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
93e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Constants representing error response for Set Report.
94e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
95e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @see BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[])
96e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
97e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte ERROR_RSP_SUCCESS = (byte) 0;
98e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte ERROR_RSP_NOT_READY = (byte) 1;
99e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte ERROR_RSP_INVALID_RPT_ID = (byte) 2;
100e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte ERROR_RSP_UNSUPPORTED_REQ = (byte) 3;
101e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte ERROR_RSP_INVALID_PARAM = (byte) 4;
102e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte ERROR_RSP_UNKNOWN = (byte) 14;
103e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
104e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
105e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Constants representing protocol mode used set by host. Default is always
106e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * {@link #PROTOCOL_REPORT_MODE} unless notified otherwise.
107e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
108e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @see BluetoothHidDeviceCallback#onSetProtocol(byte)
109e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
110e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte PROTOCOL_BOOT_MODE = (byte) 0;
111e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public static final byte PROTOCOL_REPORT_MODE = (byte) 1;
112e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
113e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    private Context mContext;
114e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
115e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    private ServiceListener mServiceListener;
116e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
1170146463d70355592da85c3605aaaef4cf0b7335eJack He    private volatile IBluetoothInputHost mService;
118e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
119e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    private BluetoothAdapter mAdapter;
120e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
121e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    private static class BluetoothHidDeviceCallbackWrapper extends IBluetoothHidDeviceCallback.Stub {
122e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
123e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        private BluetoothHidDeviceCallback mCallback;
124e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
125e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        public BluetoothHidDeviceCallbackWrapper(BluetoothHidDeviceCallback callback) {
126e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            mCallback = callback;
127e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
128e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
129e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        @Override
130e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        public void onAppStatusChanged(BluetoothDevice pluggedDevice,
131e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                BluetoothHidDeviceAppConfiguration config, boolean registered) {
132e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            mCallback.onAppStatusChanged(pluggedDevice, config, registered);
133e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
134e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
135e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        @Override
136e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        public void onConnectionStateChanged(BluetoothDevice device, int state) {
137e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            mCallback.onConnectionStateChanged(device, state);
138e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
139e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
140e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        @Override
141dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
142dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            mCallback.onGetReport(device, type, id, bufferSize);
143e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
144e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
145e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        @Override
146dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
147dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            mCallback.onSetReport(device, type, id, data);
148e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
149e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
150e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        @Override
151dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        public void onSetProtocol(BluetoothDevice device, byte protocol) {
152dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            mCallback.onSetProtocol(device, protocol);
153e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
154e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
155e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        @Override
156dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        public void onIntrData(BluetoothDevice device, byte reportId, byte[] data) {
157dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            mCallback.onIntrData(device, reportId, data);
158e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
159e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
160e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        @Override
161dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        public void onVirtualCableUnplug(BluetoothDevice device) {
162dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            mCallback.onVirtualCableUnplug(device);
163e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
164e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
165e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
166e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
167e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        new IBluetoothStateChangeCallback.Stub() {
168e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
169e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        public void onBluetoothStateChange(boolean up) {
170e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.d(TAG, "onBluetoothStateChange: up=" + up);
171e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            synchronized (mConnection) {
172e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                if (!up) {
173e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                    Log.d(TAG,"Unbinding service...");
174e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                    if (mService != null) {
175e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                        mService = null;
176e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                        try {
177e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                            mContext.unbindService(mConnection);
178e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                        } catch (IllegalArgumentException e) {
179e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                            Log.e(TAG,"onBluetoothStateChange: could not unbind service:", e);
180e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                        }
181e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                    }
182e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                } else {
183e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                    try {
184e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                        if (mService == null) {
185e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                            Log.d(TAG,"Binding HID Device service...");
186e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                            doBind();
187e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                        }
188e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                    } catch (IllegalStateException e) {
189e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                        Log.e(TAG,"onBluetoothStateChange: could not bind to HID Dev service: ", e);
190e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                    } catch (SecurityException e) {
191e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                        Log.e(TAG,"onBluetoothStateChange: could not bind to HID Dev service: ", e);
192e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                    }
193e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                }
194e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
195e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
196e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    };
197e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
1980146463d70355592da85c3605aaaef4cf0b7335eJack He    private final ServiceConnection mConnection = new ServiceConnection() {
199e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        public void onServiceConnected(ComponentName className, IBinder service) {
200e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.d(TAG, "onServiceConnected()");
2010afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov            mService = IBluetoothInputHost.Stub.asInterface(service);
202e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            if (mServiceListener != null) {
2030afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov                mServiceListener.onServiceConnected(BluetoothProfile.INPUT_HOST,
2040afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov                    BluetoothInputHost.this);
205e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
206e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
207e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        public void onServiceDisconnected(ComponentName className) {
208e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.d(TAG, "onServiceDisconnected()");
209e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            mService = null;
210e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            if (mServiceListener != null) {
2110afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov                mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_HOST);
212e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
213e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
214e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    };
215e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
2160afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov    BluetoothInputHost(Context context, ServiceListener listener) {
2170afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov        Log.v(TAG, "BluetoothInputHost");
218e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
219e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        mContext = context;
220e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        mServiceListener = listener;
221e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        mAdapter = BluetoothAdapter.getDefaultAdapter();
222e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
223e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        IBluetoothManager mgr = mAdapter.getBluetoothManager();
224e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (mgr != null) {
225e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
226e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
227e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
228e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                e.printStackTrace();
229e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
230e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
231e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
232e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        doBind();
233e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
234e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
235e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    boolean doBind() {
2360afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov        Intent intent = new Intent(IBluetoothInputHost.class.getName());
237e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
238e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        intent.setComponent(comp);
239e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
240e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                android.os.Process.myUserHandle())) {
241e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.e(TAG, "Could not bind to Bluetooth HID Device Service with " + intent);
242e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            return false;
243e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
244e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        Log.d(TAG, "Bound to HID Device Service");
245e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return true;
246e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
247e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
248e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    void close() {
249e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        Log.v(TAG, "close()");
250e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
251e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        IBluetoothManager mgr = mAdapter.getBluetoothManager();
252e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (mgr != null) {
253e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
254e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
255e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
256e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                e.printStackTrace();
257e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
258e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
259e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
260e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        synchronized (mConnection) {
261e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            if (mService != null) {
262e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                mService = null;
263e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                try {
264e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                    mContext.unbindService(mConnection);
265e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                } catch (IllegalArgumentException e) {
266e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                    Log.e(TAG,"close: could not unbind HID Dev service: ", e);
267e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                }
268e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta           }
269e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
270e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
271e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        mServiceListener = null;
272e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
273e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
274dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    /**
275dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     * {@inheritDoc}
276dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     */
277e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public List<BluetoothDevice> getConnectedDevices() {
278e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        Log.v(TAG, "getConnectedDevices()");
279dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov
2800146463d70355592da85c3605aaaef4cf0b7335eJack He        final IBluetoothInputHost service = mService;
2810146463d70355592da85c3605aaaef4cf0b7335eJack He        if (service != null) {
282dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            try {
2830146463d70355592da85c3605aaaef4cf0b7335eJack He                return service.getConnectedDevices();
284dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            } catch (RemoteException e) {
285dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                Log.e(TAG, e.toString());
286dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            }
287dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        } else {
288dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            Log.w(TAG, "Proxy not attached to service");
289dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        }
290dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov
291dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        return new ArrayList<BluetoothDevice>();
292e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
293e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
294dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    /**
295dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     * {@inheritDoc}
296dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     */
297e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
298e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
299dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov
3000146463d70355592da85c3605aaaef4cf0b7335eJack He        final IBluetoothInputHost service = mService;
3010146463d70355592da85c3605aaaef4cf0b7335eJack He        if (service != null) {
302dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            try {
3030146463d70355592da85c3605aaaef4cf0b7335eJack He                return service.getDevicesMatchingConnectionStates(states);
304dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            } catch (RemoteException e) {
305dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                Log.e(TAG, e.toString());
306dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            }
307dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        } else {
308dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            Log.w(TAG, "Proxy not attached to service");
309dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        }
310dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov
311dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        return new ArrayList<BluetoothDevice>();
312e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
313e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
314dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    /**
315dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     * {@inheritDoc}
316dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     */
317e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public int getConnectionState(BluetoothDevice device) {
318dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        Log.v(TAG, "getConnectionState(): device=" + device);
319dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov
3200146463d70355592da85c3605aaaef4cf0b7335eJack He        final IBluetoothInputHost service = mService;
3210146463d70355592da85c3605aaaef4cf0b7335eJack He        if (service != null) {
322dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            try {
3230146463d70355592da85c3605aaaef4cf0b7335eJack He                return service.getConnectionState(device);
324dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            } catch (RemoteException e) {
325dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                Log.e(TAG, e.toString());
326dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            }
327dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        } else {
328dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            Log.w(TAG, "Proxy not attached to service");
329dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        }
330e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
331e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return STATE_DISCONNECTED;
332e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
333e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
334e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
335e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Registers application to be used for HID device. Connections to HID
336e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Device are only possible when application is registered. Only one
337e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * application can be registered at time. When no longer used, application
338e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * should be unregistered using
339e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * {@link #unregisterApp(BluetoothHidDeviceAppConfiguration)}.
340e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
341e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of
342e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *             HID Device SDP record.
343e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param inQos {@link BluetoothHidDeviceAppQosSettings} object of
344e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *             Incoming QoS Settings.
345e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param outQos {@link BluetoothHidDeviceAppQosSettings} object of
346e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *             Outgoing QoS Settings.
347e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param callback {@link BluetoothHidDeviceCallback} object to which
348e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *            callback messages will be sent.
349e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
350e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
351e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public boolean registerApp(BluetoothHidDeviceAppSdpSettings sdp,
352e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            BluetoothHidDeviceAppQosSettings inQos, BluetoothHidDeviceAppQosSettings outQos,
353e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            BluetoothHidDeviceCallback callback) {
354e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        Log.v(TAG, "registerApp(): sdp=" + sdp + " inQos=" + inQos + " outQos=" + outQos
355e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                + " callback=" + callback);
356e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
357e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
358e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
359e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (sdp == null || callback == null) {
360e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            return false;
361e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
362e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
3630146463d70355592da85c3605aaaef4cf0b7335eJack He        final IBluetoothInputHost service = mService;
3640146463d70355592da85c3605aaaef4cf0b7335eJack He        if (service != null) {
365e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
366e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                BluetoothHidDeviceAppConfiguration config =
3670146463d70355592da85c3605aaaef4cf0b7335eJack He                        new BluetoothHidDeviceAppConfiguration();
368e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                BluetoothHidDeviceCallbackWrapper cbw =
3690146463d70355592da85c3605aaaef4cf0b7335eJack He                        new BluetoothHidDeviceCallbackWrapper(callback);
3700146463d70355592da85c3605aaaef4cf0b7335eJack He                result = service.registerApp(config, sdp, inQos, outQos, cbw);
371e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
372e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
373e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
374e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
375e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
376e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
377e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
378e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
379e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
380e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
381e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
382e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Unregisters application. Active connection will be disconnected and no
383e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * new connections will be allowed until registered again using
384e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * {@link #registerApp(String, String, String, byte, byte[], BluetoothHidDeviceCallback)}
385e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
386e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param config {@link BluetoothHidDeviceAppConfiguration} object as
387e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *            obtained from
388e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *            {@link BluetoothHidDeviceCallback#onAppStatusChanged(BluetoothDevice,
389e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *            BluetoothHidDeviceAppConfiguration, boolean)}
390e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
391e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
392e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
393e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public boolean unregisterApp(BluetoothHidDeviceAppConfiguration config) {
394e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        Log.v(TAG, "unregisterApp()");
395e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
396e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
397e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
3980146463d70355592da85c3605aaaef4cf0b7335eJack He        final IBluetoothInputHost service = mService;
3990146463d70355592da85c3605aaaef4cf0b7335eJack He        if (service != null) {
400e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
4010146463d70355592da85c3605aaaef4cf0b7335eJack He                result = service.unregisterApp(config);
402e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
403e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
404e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
405e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
406e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
407e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
408e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
409e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
410e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
411e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
412e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
413e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Sends report to remote host using interrupt channel.
414e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
415e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param id Report Id, as defined in descriptor. Can be 0 in case Report Id
416e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *            are not defined in descriptor.
417e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param data Report data, not including Report Id.
418e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
419e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
420dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
421e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
422e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
4230146463d70355592da85c3605aaaef4cf0b7335eJack He        final IBluetoothInputHost service = mService;
4240146463d70355592da85c3605aaaef4cf0b7335eJack He        if (service != null) {
425e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
4260146463d70355592da85c3605aaaef4cf0b7335eJack He                result = service.sendReport(device, id, data);
427e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
428e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
429e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
430e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
431e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
432e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
433e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
434e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
435e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
436e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
437e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
438e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Sends report to remote host as reply for GET_REPORT request from
439dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     * {@link BluetoothHidDeviceCallback#onGetReport(BluetoothDevice, byte, byte, int)}.
440e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
441e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param type Report Type, as in request.
442e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param id Report Id, as in request.
443e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param data Report data, not including Report Id.
444e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
445e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
446dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {
447dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        Log.v(TAG, "replyReport(): device=" + device + " type=" + type + " id=" + id);
448e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
449e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
450e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
4510146463d70355592da85c3605aaaef4cf0b7335eJack He        final IBluetoothInputHost service = mService;
4520146463d70355592da85c3605aaaef4cf0b7335eJack He        if (service != null) {
453e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
4540146463d70355592da85c3605aaaef4cf0b7335eJack He                result = service.replyReport(device, type, id, data);
455e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
456e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
457e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
458e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
459e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
460e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
461e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
462e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
463e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
464e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
465e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
466e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Sends error handshake message as reply for invalid SET_REPORT request
467dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     * from {@link BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])}.
468e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
469e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param error Error to be sent for SET_REPORT via HANDSHAKE.
470e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
471e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
472dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    public boolean reportError(BluetoothDevice device, byte error) {
473dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        Log.v(TAG, "reportError(): device=" + device + " error=" + error);
474e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
475e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
476e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
4770146463d70355592da85c3605aaaef4cf0b7335eJack He        final IBluetoothInputHost service = mService;
4780146463d70355592da85c3605aaaef4cf0b7335eJack He        if (service != null) {
479e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
4800146463d70355592da85c3605aaaef4cf0b7335eJack He                result = service.reportError(device, error);
481e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
482e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
483e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
484e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
485e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
486e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
487e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
488e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
489e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
490e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
491e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
492e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Sends Virtual Cable Unplug to currently connected host.
493e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
494e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
495e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
496dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    public boolean unplug(BluetoothDevice device) {
497dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        Log.v(TAG, "unplug(): device=" + device);
498e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
499e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
500e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
5010146463d70355592da85c3605aaaef4cf0b7335eJack He        final IBluetoothInputHost service = mService;
5020146463d70355592da85c3605aaaef4cf0b7335eJack He        if (service != null) {
503e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
5040146463d70355592da85c3605aaaef4cf0b7335eJack He                result = service.unplug(device);
505e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
506e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
507e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
508e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
509e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
510e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
511e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
512e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
513e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
514e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
515e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
516e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Initiates connection to host which currently has Virtual Cable
517e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * established with device.
518e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
519e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
520e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
521dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    public boolean connect(BluetoothDevice device) {
522dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        Log.v(TAG, "connect(): device=" + device);
523e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
524e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
525e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
5260146463d70355592da85c3605aaaef4cf0b7335eJack He        final IBluetoothInputHost service = mService;
5270146463d70355592da85c3605aaaef4cf0b7335eJack He        if (service != null) {
528e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
5290146463d70355592da85c3605aaaef4cf0b7335eJack He                result = service.connect(device);
530e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
531e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
532e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
533e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
534e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
535e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
536e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
537e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
538e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
539e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
540e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
541e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Disconnects from currently connected host.
542e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
543e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
544e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
545dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    public boolean disconnect(BluetoothDevice device) {
546dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        Log.v(TAG, "disconnect(): device=" + device);
547e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
548e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
549e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
5500146463d70355592da85c3605aaaef4cf0b7335eJack He        final IBluetoothInputHost service = mService;
5510146463d70355592da85c3605aaaef4cf0b7335eJack He        if (service != null) {
552e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
5530146463d70355592da85c3605aaaef4cf0b7335eJack He                result = service.disconnect(device);
554e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
555e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
556e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
557e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
558e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
559e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
560e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
561e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
562e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
563e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta}
564