blob: e3d763ab9b1e63faed1042dd67939146aa148593 [file] [log] [blame]
Hemant Guptae88fd4b2014-04-18 11:22:45 +05301/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.bluetooth;
18
Ivan Podogov0afe1902016-12-23 11:52:21 +000019import android.annotation.SdkConstant;
20import android.annotation.SdkConstant.SdkConstantType;
Hemant Guptae88fd4b2014-04-18 11:22:45 +053021import android.content.ComponentName;
22import android.content.Context;
23import android.content.Intent;
24import android.content.ServiceConnection;
25import android.os.IBinder;
26import android.os.RemoteException;
27import android.util.Log;
28
Ivan Podogovdd87cd32016-12-30 14:43:29 +000029import java.util.ArrayList;
Jack Hea355e5e2017-08-22 16:06:54 -070030import java.util.Arrays;
Hemant Guptae88fd4b2014-04-18 11:22:45 +053031import java.util.List;
32
33/**
Hansong Zhangfa377b42017-09-27 14:17:20 -070034 * Provides the public APIs to control the Bluetooth HID Device
35 * profile.
36 *
37 * BluetoothHidDevice is a proxy object for controlling the Bluetooth HID
38 * Device Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
39 * the BluetoothHidDevice proxy object.
40 *
41 * {@hide}
Hemant Guptae88fd4b2014-04-18 11:22:45 +053042 */
Hansong Zhangc26c76c2017-10-20 15:55:59 -070043public final class BluetoothHidDevice implements BluetoothProfile {
Hemant Guptae88fd4b2014-04-18 11:22:45 +053044
Hansong Zhangc26c76c2017-10-20 15:55:59 -070045 private static final String TAG = BluetoothHidDevice.class.getSimpleName();
Hemant Guptae88fd4b2014-04-18 11:22:45 +053046
Ivan Podogov0afe1902016-12-23 11:52:21 +000047 /**
48 * Intent used to broadcast the change in connection state of the Input
49 * Host profile.
50 *
51 * <p>This intent will have 3 extras:
52 * <ul>
Jack Hea355e5e2017-08-22 16:06:54 -070053 * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
54 * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
55 * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
Ivan Podogov0afe1902016-12-23 11:52:21 +000056 * </ul>
57 *
58 * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
59 * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
60 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
61 *
62 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
63 * receive.
64 */
65 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
Hemant Guptae88fd4b2014-04-18 11:22:45 +053066 public static final String ACTION_CONNECTION_STATE_CHANGED =
Hansong Zhangc26c76c2017-10-20 15:55:59 -070067 "android.bluetooth.hiddevice.profile.action.CONNECTION_STATE_CHANGED";
Hemant Guptae88fd4b2014-04-18 11:22:45 +053068
69 /**
70 * Constants representing device subclass.
71 *
Hansong Zhangfa377b42017-09-27 14:17:20 -070072 * @see #registerApp
73 * (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
74 * BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceCallback)
Hemant Guptae88fd4b2014-04-18 11:22:45 +053075 */
76 public static final byte SUBCLASS1_NONE = (byte) 0x00;
77 public static final byte SUBCLASS1_KEYBOARD = (byte) 0x40;
78 public static final byte SUBCLASS1_MOUSE = (byte) 0x80;
79 public static final byte SUBCLASS1_COMBO = (byte) 0xC0;
80
81 public static final byte SUBCLASS2_UNCATEGORIZED = (byte) 0x00;
82 public static final byte SUBCLASS2_JOYSTICK = (byte) 0x01;
83 public static final byte SUBCLASS2_GAMEPAD = (byte) 0x02;
84 public static final byte SUBCLASS2_REMOTE_CONTROL = (byte) 0x03;
85 public static final byte SUBCLASS2_SENSING_DEVICE = (byte) 0x04;
Hansong Zhang9eb138b2017-09-29 09:26:09 -070086 public static final byte SUBCLASS2_DIGITIZER_TABLET = (byte) 0x05;
Hemant Guptae88fd4b2014-04-18 11:22:45 +053087 public static final byte SUBCLASS2_CARD_READER = (byte) 0x06;
88
89 /**
90 * Constants representing report types.
91 *
Hansong Zhangfa377b42017-09-27 14:17:20 -070092 * @see BluetoothHidDeviceCallback#onGetReport(BluetoothDevice, byte, byte, int)
93 * @see BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])
94 * @see BluetoothHidDeviceCallback#onIntrData(BluetoothDevice, byte, byte[])
Hemant Guptae88fd4b2014-04-18 11:22:45 +053095 */
96 public static final byte REPORT_TYPE_INPUT = (byte) 1;
97 public static final byte REPORT_TYPE_OUTPUT = (byte) 2;
98 public static final byte REPORT_TYPE_FEATURE = (byte) 3;
99
100 /**
101 * Constants representing error response for Set Report.
102 *
Hansong Zhangfa377b42017-09-27 14:17:20 -0700103 * @see BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530104 */
105 public static final byte ERROR_RSP_SUCCESS = (byte) 0;
106 public static final byte ERROR_RSP_NOT_READY = (byte) 1;
107 public static final byte ERROR_RSP_INVALID_RPT_ID = (byte) 2;
108 public static final byte ERROR_RSP_UNSUPPORTED_REQ = (byte) 3;
109 public static final byte ERROR_RSP_INVALID_PARAM = (byte) 4;
110 public static final byte ERROR_RSP_UNKNOWN = (byte) 14;
111
112 /**
113 * Constants representing protocol mode used set by host. Default is always
114 * {@link #PROTOCOL_REPORT_MODE} unless notified otherwise.
115 *
Hansong Zhangfa377b42017-09-27 14:17:20 -0700116 * @see BluetoothHidDeviceCallback#onSetProtocol(BluetoothDevice, byte)
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530117 */
118 public static final byte PROTOCOL_BOOT_MODE = (byte) 0;
119 public static final byte PROTOCOL_REPORT_MODE = (byte) 1;
120
121 private Context mContext;
122
123 private ServiceListener mServiceListener;
124
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700125 private volatile IBluetoothHidDevice mService;
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530126
127 private BluetoothAdapter mAdapter;
128
Jack Hea355e5e2017-08-22 16:06:54 -0700129 private static class BluetoothHidDeviceCallbackWrapper extends
130 IBluetoothHidDeviceCallback.Stub {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530131
132 private BluetoothHidDeviceCallback mCallback;
133
134 public BluetoothHidDeviceCallbackWrapper(BluetoothHidDeviceCallback callback) {
135 mCallback = callback;
136 }
137
138 @Override
139 public void onAppStatusChanged(BluetoothDevice pluggedDevice,
140 BluetoothHidDeviceAppConfiguration config, boolean registered) {
141 mCallback.onAppStatusChanged(pluggedDevice, config, registered);
142 }
143
144 @Override
145 public void onConnectionStateChanged(BluetoothDevice device, int state) {
146 mCallback.onConnectionStateChanged(device, state);
147 }
148
149 @Override
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000150 public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
151 mCallback.onGetReport(device, type, id, bufferSize);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530152 }
153
154 @Override
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000155 public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
156 mCallback.onSetReport(device, type, id, data);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530157 }
158
159 @Override
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000160 public void onSetProtocol(BluetoothDevice device, byte protocol) {
161 mCallback.onSetProtocol(device, protocol);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530162 }
163
164 @Override
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000165 public void onIntrData(BluetoothDevice device, byte reportId, byte[] data) {
166 mCallback.onIntrData(device, reportId, data);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530167 }
168
169 @Override
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000170 public void onVirtualCableUnplug(BluetoothDevice device) {
171 mCallback.onVirtualCableUnplug(device);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530172 }
173 }
174
Jack He2992cd02017-08-22 21:21:23 -0700175 private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
Jack Hea355e5e2017-08-22 16:06:54 -0700176 new IBluetoothStateChangeCallback.Stub() {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530177
Jack Hea355e5e2017-08-22 16:06:54 -0700178 public void onBluetoothStateChange(boolean up) {
179 Log.d(TAG, "onBluetoothStateChange: up=" + up);
180 synchronized (mConnection) {
Hansong Zhangfa377b42017-09-27 14:17:20 -0700181 if (up) {
Jack Hea355e5e2017-08-22 16:06:54 -0700182 try {
183 if (mService == null) {
184 Log.d(TAG, "Binding HID Device service...");
185 doBind();
186 }
187 } catch (IllegalStateException e) {
188 Log.e(TAG,
189 "onBluetoothStateChange: could not bind to HID Dev "
Hansong Zhangfa377b42017-09-27 14:17:20 -0700190 + "service: ", e);
Jack Hea355e5e2017-08-22 16:06:54 -0700191 } catch (SecurityException e) {
192 Log.e(TAG,
193 "onBluetoothStateChange: could not bind to HID Dev "
Hansong Zhangfa377b42017-09-27 14:17:20 -0700194 + "service: ", e);
Jack Hea355e5e2017-08-22 16:06:54 -0700195 }
Hansong Zhangfa377b42017-09-27 14:17:20 -0700196 } else {
197 Log.d(TAG, "Unbinding service...");
198 doUnbind();
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530199 }
200 }
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530201 }
Jack Hea355e5e2017-08-22 16:06:54 -0700202 };
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530203
Jack He16eeac32017-08-17 12:11:18 -0700204 private final ServiceConnection mConnection = new ServiceConnection() {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530205 public void onServiceConnected(ComponentName className, IBinder service) {
206 Log.d(TAG, "onServiceConnected()");
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700207 mService = IBluetoothHidDevice.Stub.asInterface(service);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530208 if (mServiceListener != null) {
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700209 mServiceListener.onServiceConnected(BluetoothProfile.HID_DEVICE,
210 BluetoothHidDevice.this);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530211 }
212 }
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530213 public void onServiceDisconnected(ComponentName className) {
214 Log.d(TAG, "onServiceDisconnected()");
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530215 mService = null;
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530216 if (mServiceListener != null) {
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700217 mServiceListener.onServiceDisconnected(BluetoothProfile.HID_DEVICE);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530218 }
219 }
220 };
221
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700222 BluetoothHidDevice(Context context, ServiceListener listener) {
223 Log.v(TAG, "BluetoothHidDevice");
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530224
225 mContext = context;
226 mServiceListener = listener;
227 mAdapter = BluetoothAdapter.getDefaultAdapter();
228
229 IBluetoothManager mgr = mAdapter.getBluetoothManager();
230 if (mgr != null) {
231 try {
232 mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
233 } catch (RemoteException e) {
234 e.printStackTrace();
235 }
236 }
237
238 doBind();
239 }
240
241 boolean doBind() {
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700242 Intent intent = new Intent(IBluetoothHidDevice.class.getName());
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530243 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
244 intent.setComponent(comp);
245 if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
246 android.os.Process.myUserHandle())) {
247 Log.e(TAG, "Could not bind to Bluetooth HID Device Service with " + intent);
248 return false;
249 }
250 Log.d(TAG, "Bound to HID Device Service");
251 return true;
252 }
253
Hansong Zhangfa377b42017-09-27 14:17:20 -0700254 void doUnbind() {
255 Log.d(TAG, "Unbinding HidDevService");
256 if (mService != null) {
257 mService = null;
258 try {
259 mContext.unbindService(mConnection);
260 } catch (IllegalArgumentException e) {
261 Log.e(TAG, "Unable to unbind HidDevService", e);
262 }
263 }
264 }
265
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530266 void close() {
267 Log.v(TAG, "close()");
268
269 IBluetoothManager mgr = mAdapter.getBluetoothManager();
270 if (mgr != null) {
271 try {
272 mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
273 } catch (RemoteException e) {
274 e.printStackTrace();
275 }
276 }
277
278 synchronized (mConnection) {
Hansong Zhangfa377b42017-09-27 14:17:20 -0700279 doUnbind();
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530280 }
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530281 mServiceListener = null;
282 }
283
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000284 /**
285 * {@inheritDoc}
286 */
Jack He2992cd02017-08-22 21:21:23 -0700287 @Override
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530288 public List<BluetoothDevice> getConnectedDevices() {
289 Log.v(TAG, "getConnectedDevices()");
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000290
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700291 final IBluetoothHidDevice service = mService;
Jack He16eeac32017-08-17 12:11:18 -0700292 if (service != null) {
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000293 try {
Jack He16eeac32017-08-17 12:11:18 -0700294 return service.getConnectedDevices();
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000295 } catch (RemoteException e) {
296 Log.e(TAG, e.toString());
297 }
298 } else {
299 Log.w(TAG, "Proxy not attached to service");
300 }
301
302 return new ArrayList<BluetoothDevice>();
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530303 }
304
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000305 /**
306 * {@inheritDoc}
307 */
Jack He2992cd02017-08-22 21:21:23 -0700308 @Override
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530309 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
310 Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000311
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700312 final IBluetoothHidDevice service = mService;
Jack He16eeac32017-08-17 12:11:18 -0700313 if (service != null) {
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000314 try {
Jack He16eeac32017-08-17 12:11:18 -0700315 return service.getDevicesMatchingConnectionStates(states);
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000316 } catch (RemoteException e) {
317 Log.e(TAG, e.toString());
318 }
319 } else {
320 Log.w(TAG, "Proxy not attached to service");
321 }
322
323 return new ArrayList<BluetoothDevice>();
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530324 }
325
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000326 /**
327 * {@inheritDoc}
328 */
Jack He2992cd02017-08-22 21:21:23 -0700329 @Override
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530330 public int getConnectionState(BluetoothDevice device) {
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000331 Log.v(TAG, "getConnectionState(): device=" + device);
332
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700333 final IBluetoothHidDevice service = mService;
Jack He16eeac32017-08-17 12:11:18 -0700334 if (service != null) {
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000335 try {
Jack He16eeac32017-08-17 12:11:18 -0700336 return service.getConnectionState(device);
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000337 } catch (RemoteException e) {
338 Log.e(TAG, e.toString());
339 }
340 } else {
341 Log.w(TAG, "Proxy not attached to service");
342 }
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530343
344 return STATE_DISCONNECTED;
345 }
346
347 /**
348 * Registers application to be used for HID device. Connections to HID
349 * Device are only possible when application is registered. Only one
350 * application can be registered at time. When no longer used, application
351 * should be unregistered using
352 * {@link #unregisterApp(BluetoothHidDeviceAppConfiguration)}.
353 *
Jack Hea355e5e2017-08-22 16:06:54 -0700354 * @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of HID Device SDP record.
355 * @param inQos {@link BluetoothHidDeviceAppQosSettings} object of Incoming QoS Settings.
356 * @param outQos {@link BluetoothHidDeviceAppQosSettings} object of Outgoing QoS Settings.
357 * @param callback {@link BluetoothHidDeviceCallback} object to which callback messages will be
358 * sent.
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530359 * @return
360 */
361 public boolean registerApp(BluetoothHidDeviceAppSdpSettings sdp,
362 BluetoothHidDeviceAppQosSettings inQos, BluetoothHidDeviceAppQosSettings outQos,
363 BluetoothHidDeviceCallback callback) {
364 Log.v(TAG, "registerApp(): sdp=" + sdp + " inQos=" + inQos + " outQos=" + outQos
365 + " callback=" + callback);
366
367 boolean result = false;
368
369 if (sdp == null || callback == null) {
370 return false;
371 }
372
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700373 final IBluetoothHidDevice service = mService;
Jack He16eeac32017-08-17 12:11:18 -0700374 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530375 try {
376 BluetoothHidDeviceAppConfiguration config =
Jack Hea355e5e2017-08-22 16:06:54 -0700377 new BluetoothHidDeviceAppConfiguration();
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530378 BluetoothHidDeviceCallbackWrapper cbw =
Jack Hea355e5e2017-08-22 16:06:54 -0700379 new BluetoothHidDeviceCallbackWrapper(callback);
Jack He16eeac32017-08-17 12:11:18 -0700380 result = service.registerApp(config, sdp, inQos, outQos, cbw);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530381 } catch (RemoteException e) {
382 Log.e(TAG, e.toString());
383 }
384 } else {
385 Log.w(TAG, "Proxy not attached to service");
386 }
387
388 return result;
389 }
390
391 /**
392 * Unregisters application. Active connection will be disconnected and no
393 * new connections will be allowed until registered again using
Hansong Zhangfa377b42017-09-27 14:17:20 -0700394 * {@link #registerApp
395 * (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
396 * BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceCallback)}
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530397 *
Jack Hea355e5e2017-08-22 16:06:54 -0700398 * @param config {@link BluetoothHidDeviceAppConfiguration} object as obtained from {@link
399 * BluetoothHidDeviceCallback#onAppStatusChanged(BluetoothDevice,
400 * BluetoothHidDeviceAppConfiguration,
401 * boolean)}
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530402 * @return
403 */
404 public boolean unregisterApp(BluetoothHidDeviceAppConfiguration config) {
405 Log.v(TAG, "unregisterApp()");
406
407 boolean result = false;
408
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700409 final IBluetoothHidDevice service = mService;
Jack He16eeac32017-08-17 12:11:18 -0700410 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530411 try {
Jack He16eeac32017-08-17 12:11:18 -0700412 result = service.unregisterApp(config);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530413 } catch (RemoteException e) {
414 Log.e(TAG, e.toString());
415 }
416 } else {
417 Log.w(TAG, "Proxy not attached to service");
418 }
419
420 return result;
421 }
422
423 /**
424 * Sends report to remote host using interrupt channel.
425 *
Jack Hea355e5e2017-08-22 16:06:54 -0700426 * @param id Report Id, as defined in descriptor. Can be 0 in case Report Id are not defined in
427 * descriptor.
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530428 * @param data Report data, not including Report Id.
429 * @return
430 */
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000431 public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530432 boolean result = false;
433
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700434 final IBluetoothHidDevice service = mService;
Jack He16eeac32017-08-17 12:11:18 -0700435 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530436 try {
Jack He16eeac32017-08-17 12:11:18 -0700437 result = service.sendReport(device, id, data);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530438 } catch (RemoteException e) {
439 Log.e(TAG, e.toString());
440 }
441 } else {
442 Log.w(TAG, "Proxy not attached to service");
443 }
444
445 return result;
446 }
447
448 /**
449 * Sends report to remote host as reply for GET_REPORT request from
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000450 * {@link BluetoothHidDeviceCallback#onGetReport(BluetoothDevice, byte, byte, int)}.
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530451 *
452 * @param type Report Type, as in request.
453 * @param id Report Id, as in request.
454 * @param data Report data, not including Report Id.
455 * @return
456 */
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000457 public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {
458 Log.v(TAG, "replyReport(): device=" + device + " type=" + type + " id=" + id);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530459
460 boolean result = false;
461
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700462 final IBluetoothHidDevice service = mService;
Jack He16eeac32017-08-17 12:11:18 -0700463 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530464 try {
Jack He16eeac32017-08-17 12:11:18 -0700465 result = service.replyReport(device, type, id, data);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530466 } catch (RemoteException e) {
467 Log.e(TAG, e.toString());
468 }
469 } else {
470 Log.w(TAG, "Proxy not attached to service");
471 }
472
473 return result;
474 }
475
476 /**
477 * Sends error handshake message as reply for invalid SET_REPORT request
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000478 * from {@link BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])}.
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530479 *
480 * @param error Error to be sent for SET_REPORT via HANDSHAKE.
481 * @return
482 */
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000483 public boolean reportError(BluetoothDevice device, byte error) {
484 Log.v(TAG, "reportError(): device=" + device + " error=" + error);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530485
486 boolean result = false;
487
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700488 final IBluetoothHidDevice service = mService;
Jack He16eeac32017-08-17 12:11:18 -0700489 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530490 try {
Jack He16eeac32017-08-17 12:11:18 -0700491 result = service.reportError(device, error);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530492 } catch (RemoteException e) {
493 Log.e(TAG, e.toString());
494 }
495 } else {
496 Log.w(TAG, "Proxy not attached to service");
497 }
498
499 return result;
500 }
501
502 /**
503 * Sends Virtual Cable Unplug to currently connected host.
504 *
505 * @return
506 */
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000507 public boolean unplug(BluetoothDevice device) {
508 Log.v(TAG, "unplug(): device=" + device);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530509
510 boolean result = false;
511
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700512 final IBluetoothHidDevice service = mService;
Jack He16eeac32017-08-17 12:11:18 -0700513 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530514 try {
Jack He16eeac32017-08-17 12:11:18 -0700515 result = service.unplug(device);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530516 } catch (RemoteException e) {
517 Log.e(TAG, e.toString());
518 }
519 } else {
520 Log.w(TAG, "Proxy not attached to service");
521 }
522
523 return result;
524 }
525
526 /**
527 * Initiates connection to host which currently has Virtual Cable
528 * established with device.
529 *
530 * @return
531 */
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000532 public boolean connect(BluetoothDevice device) {
533 Log.v(TAG, "connect(): device=" + device);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530534
535 boolean result = false;
536
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700537 final IBluetoothHidDevice service = mService;
Jack He16eeac32017-08-17 12:11:18 -0700538 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530539 try {
Jack He16eeac32017-08-17 12:11:18 -0700540 result = service.connect(device);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530541 } catch (RemoteException e) {
542 Log.e(TAG, e.toString());
543 }
544 } else {
545 Log.w(TAG, "Proxy not attached to service");
546 }
547
548 return result;
549 }
550
551 /**
552 * Disconnects from currently connected host.
553 *
554 * @return
555 */
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000556 public boolean disconnect(BluetoothDevice device) {
557 Log.v(TAG, "disconnect(): device=" + device);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530558
559 boolean result = false;
560
Hansong Zhangc26c76c2017-10-20 15:55:59 -0700561 final IBluetoothHidDevice service = mService;
Jack He16eeac32017-08-17 12:11:18 -0700562 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530563 try {
Jack He16eeac32017-08-17 12:11:18 -0700564 result = service.disconnect(device);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530565 } catch (RemoteException e) {
566 Log.e(TAG, e.toString());
567 }
568 } else {
569 Log.w(TAG, "Proxy not attached to service");
570 }
571
572 return result;
573 }
574}