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
29e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Guptaimport java.util.Arrays;
30dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogovimport java.util.ArrayList;
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
1170afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov    private 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
198e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    private ServiceConnection mConnection = new ServiceConnection() {
199e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
200e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        public void onServiceConnected(ComponentName className, IBinder service) {
201e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.d(TAG, "onServiceConnected()");
202e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
2030afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov            mService = IBluetoothInputHost.Stub.asInterface(service);
204e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
205e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            if (mServiceListener != null) {
2060afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov                mServiceListener.onServiceConnected(BluetoothProfile.INPUT_HOST,
2070afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov                    BluetoothInputHost.this);
208e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
209e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
210e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
211e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        public void onServiceDisconnected(ComponentName className) {
212e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.d(TAG, "onServiceDisconnected()");
213e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
214e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            mService = null;
215e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
216e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            if (mServiceListener != null) {
2170afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov                mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_HOST);
218e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
219e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
220e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    };
221e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
2220afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov    BluetoothInputHost(Context context, ServiceListener listener) {
2230afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov        Log.v(TAG, "BluetoothInputHost");
224e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
225e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        mContext = context;
226e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        mServiceListener = listener;
227e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        mAdapter = BluetoothAdapter.getDefaultAdapter();
228e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
229e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        IBluetoothManager mgr = mAdapter.getBluetoothManager();
230e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (mgr != null) {
231e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
232e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
233e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
234e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                e.printStackTrace();
235e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
236e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
237e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
238e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        doBind();
239e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
240e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
241e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    boolean doBind() {
2420afe190af52d83c5e52fa994e53c48e33e8e3bf4Ivan Podogov        Intent intent = new Intent(IBluetoothInputHost.class.getName());
243e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
244e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        intent.setComponent(comp);
245e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
246e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                android.os.Process.myUserHandle())) {
247e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.e(TAG, "Could not bind to Bluetooth HID Device Service with " + intent);
248e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            return false;
249e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
250e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        Log.d(TAG, "Bound to HID Device Service");
251e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return true;
252e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
253e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
254e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    void close() {
255e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        Log.v(TAG, "close()");
256e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
257e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        IBluetoothManager mgr = mAdapter.getBluetoothManager();
258e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (mgr != null) {
259e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
260e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
261e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
262e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                e.printStackTrace();
263e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
264e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
265e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
266e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        synchronized (mConnection) {
267e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            if (mService != null) {
268e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                mService = null;
269e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                try {
270e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                    mContext.unbindService(mConnection);
271e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                } catch (IllegalArgumentException e) {
272e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                    Log.e(TAG,"close: could not unbind HID Dev service: ", e);
273e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                }
274e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta           }
275e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
276e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
277e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        mServiceListener = null;
278e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
279e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
280dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    /**
281dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     * {@inheritDoc}
282dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     */
283e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public List<BluetoothDevice> getConnectedDevices() {
284e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        Log.v(TAG, "getConnectedDevices()");
285dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov
286dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        if (mService != null) {
287dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            try {
288dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                return mService.getConnectedDevices();
289dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            } catch (RemoteException e) {
290dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                Log.e(TAG, e.toString());
291dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            }
292dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        } else {
293dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            Log.w(TAG, "Proxy not attached to service");
294dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        }
295dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov
296dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        return new ArrayList<BluetoothDevice>();
297e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
298e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
299dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    /**
300dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     * {@inheritDoc}
301dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     */
302e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
303e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
304dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov
305dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        if (mService != null) {
306dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            try {
307dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                return mService.getDevicesMatchingConnectionStates(states);
308dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            } catch (RemoteException e) {
309dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                Log.e(TAG, e.toString());
310dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            }
311dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        } else {
312dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            Log.w(TAG, "Proxy not attached to service");
313dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        }
314dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov
315dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        return new ArrayList<BluetoothDevice>();
316e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
317e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
318dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    /**
319dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     * {@inheritDoc}
320dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     */
321e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public int getConnectionState(BluetoothDevice device) {
322dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        Log.v(TAG, "getConnectionState(): device=" + device);
323dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov
324dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        if (mService != null) {
325dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            try {
326dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                return mService.getConnectionState(device);
327dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            } catch (RemoteException e) {
328dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                Log.e(TAG, e.toString());
329dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            }
330dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        } else {
331dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov            Log.w(TAG, "Proxy not attached to service");
332dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        }
333e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
334e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return STATE_DISCONNECTED;
335e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
336e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
337e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
338e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Registers application to be used for HID device. Connections to HID
339e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Device are only possible when application is registered. Only one
340e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * application can be registered at time. When no longer used, application
341e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * should be unregistered using
342e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * {@link #unregisterApp(BluetoothHidDeviceAppConfiguration)}.
343e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
344e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of
345e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *             HID Device SDP record.
346e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param inQos {@link BluetoothHidDeviceAppQosSettings} object of
347e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *             Incoming QoS Settings.
348e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param outQos {@link BluetoothHidDeviceAppQosSettings} object of
349e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *             Outgoing QoS Settings.
350e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param callback {@link BluetoothHidDeviceCallback} object to which
351e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *            callback messages will be sent.
352e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
353e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
354e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public boolean registerApp(BluetoothHidDeviceAppSdpSettings sdp,
355e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            BluetoothHidDeviceAppQosSettings inQos, BluetoothHidDeviceAppQosSettings outQos,
356e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            BluetoothHidDeviceCallback callback) {
357e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        Log.v(TAG, "registerApp(): sdp=" + sdp + " inQos=" + inQos + " outQos=" + outQos
358e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                + " callback=" + callback);
359e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
360e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
361e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
362e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (sdp == null || callback == null) {
363e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            return false;
364e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
365e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
366e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (mService != null) {
367e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
368e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                BluetoothHidDeviceAppConfiguration config =
369e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                    new BluetoothHidDeviceAppConfiguration();
370e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                BluetoothHidDeviceCallbackWrapper cbw =
371e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                    new BluetoothHidDeviceCallbackWrapper(callback);
372e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                result = mService.registerApp(config, sdp, inQos, outQos, cbw);
373e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
374e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
375e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
376e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
377e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
378e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
379e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
380e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
381e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
382e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
383e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
384e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Unregisters application. Active connection will be disconnected and no
385e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * new connections will be allowed until registered again using
386e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * {@link #registerApp(String, String, String, byte, byte[], BluetoothHidDeviceCallback)}
387e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
388e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param config {@link BluetoothHidDeviceAppConfiguration} object as
389e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *            obtained from
390e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *            {@link BluetoothHidDeviceCallback#onAppStatusChanged(BluetoothDevice,
391e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *            BluetoothHidDeviceAppConfiguration, boolean)}
392e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
393e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
394e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
395e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    public boolean unregisterApp(BluetoothHidDeviceAppConfiguration config) {
396e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        Log.v(TAG, "unregisterApp()");
397e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
398e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
399e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
400e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (mService != null) {
401e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
402e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                result = mService.unregisterApp(config);
403e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
404e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
405e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
406e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
407e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
408e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
409e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
410e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
411e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
412e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
413e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
414e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Sends report to remote host using interrupt channel.
415e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
416e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param id Report Id, as defined in descriptor. Can be 0 in case Report Id
417e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *            are not defined in descriptor.
418e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param data Report data, not including Report Id.
419e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
420e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
421dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
422e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
423e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
424e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (mService != null) {
425e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
426dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                result = mService.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
451e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (mService != null) {
452e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
453dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                result = mService.replyReport(device, type, id, data);
454e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
455e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
456e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
457e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
458e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
459e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
460e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
461e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
462e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
463e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
464e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
465e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Sends error handshake message as reply for invalid SET_REPORT request
466dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov     * from {@link BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])}.
467e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
468e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @param error Error to be sent for SET_REPORT via HANDSHAKE.
469e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
470e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
471dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    public boolean reportError(BluetoothDevice device, byte error) {
472dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        Log.v(TAG, "reportError(): device=" + device + " error=" + error);
473e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
474e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
475e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
476e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (mService != null) {
477e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
478dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                result = mService.reportError(device, error);
479e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
480e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
481e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
482e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
483e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
484e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
485e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
486e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
487e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
488e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
489e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
490e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Sends Virtual Cable Unplug to currently connected host.
491e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
492e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
493e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
494dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    public boolean unplug(BluetoothDevice device) {
495dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        Log.v(TAG, "unplug(): device=" + device);
496e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
497e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
498e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
499e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (mService != null) {
500e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
501dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                result = mService.unplug(device);
502e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
503e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
504e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
505e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
506e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
507e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
508e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
509e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
510e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
511e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
512e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
513e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Initiates connection to host which currently has Virtual Cable
514e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * established with device.
515e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
516e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
517e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
518dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    public boolean connect(BluetoothDevice device) {
519dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        Log.v(TAG, "connect(): device=" + device);
520e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
521e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
522e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
523e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (mService != null) {
524e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
525dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                result = mService.connect(device);
526e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
527e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
528e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
529e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
530e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
531e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
532e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
533e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
534e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
535e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
536e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    /**
537e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * Disconnects from currently connected host.
538e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     *
539e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     * @return
540e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta     */
541dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov    public boolean disconnect(BluetoothDevice device) {
542dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov        Log.v(TAG, "disconnect(): device=" + device);
543e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
544e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        boolean result = false;
545e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
546e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        if (mService != null) {
547e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            try {
548dd87cd3bb611b7449edfa17d59d9b962784750eeIvan Podogov                result = mService.disconnect(device);
549e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            } catch (RemoteException e) {
550e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta                Log.e(TAG, e.toString());
551e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            }
552e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        } else {
553e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta            Log.w(TAG, "Proxy not attached to service");
554e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        }
555e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta
556e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta        return result;
557e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta    }
558e88fd4b5940a855e961cffa36e93f844a44cd2d4Hemant Gupta}
559