blob: e18d9d1be51bded51697592ad4984b5a78c65cad [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/**
34 * @hide
35 */
Ivan Podogov0afe1902016-12-23 11:52:21 +000036public final class BluetoothInputHost implements BluetoothProfile {
Hemant Guptae88fd4b2014-04-18 11:22:45 +053037
Ivan Podogov0afe1902016-12-23 11:52:21 +000038 private static final String TAG = BluetoothInputHost.class.getSimpleName();
Hemant Guptae88fd4b2014-04-18 11:22:45 +053039
Ivan Podogov0afe1902016-12-23 11:52:21 +000040 /**
41 * Intent used to broadcast the change in connection state of the Input
42 * Host profile.
43 *
44 * <p>This intent will have 3 extras:
45 * <ul>
Jack Hea355e5e2017-08-22 16:06:54 -070046 * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
47 * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
48 * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
Ivan Podogov0afe1902016-12-23 11:52:21 +000049 * </ul>
50 *
51 * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
52 * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
53 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
54 *
55 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
56 * receive.
57 */
58 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
Hemant Guptae88fd4b2014-04-18 11:22:45 +053059 public static final String ACTION_CONNECTION_STATE_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -070060 "android.bluetooth.inputhost.profile.action.CONNECTION_STATE_CHANGED";
Hemant Guptae88fd4b2014-04-18 11:22:45 +053061
62 /**
63 * Constants representing device subclass.
64 *
Jack Hea355e5e2017-08-22 16:06:54 -070065 * @see #registerApp(String, String, String, byte, byte[], BluetoothHidDeviceCallback)
Hemant Guptae88fd4b2014-04-18 11:22:45 +053066 */
67 public static final byte SUBCLASS1_NONE = (byte) 0x00;
68 public static final byte SUBCLASS1_KEYBOARD = (byte) 0x40;
69 public static final byte SUBCLASS1_MOUSE = (byte) 0x80;
70 public static final byte SUBCLASS1_COMBO = (byte) 0xC0;
71
72 public static final byte SUBCLASS2_UNCATEGORIZED = (byte) 0x00;
73 public static final byte SUBCLASS2_JOYSTICK = (byte) 0x01;
74 public static final byte SUBCLASS2_GAMEPAD = (byte) 0x02;
75 public static final byte SUBCLASS2_REMOTE_CONTROL = (byte) 0x03;
76 public static final byte SUBCLASS2_SENSING_DEVICE = (byte) 0x04;
Hansong Zhangecd09fb2017-09-27 16:59:01 -070077 public static final byte SUBCLASS2_DIGITIZER_TABLET = (byte) 0x05;
Hemant Guptae88fd4b2014-04-18 11:22:45 +053078 public static final byte SUBCLASS2_CARD_READER = (byte) 0x06;
79
80 /**
81 * Constants representing report types.
82 *
83 * @see BluetoothHidDeviceCallback#onGetReport(byte, byte, int)
84 * @see BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[])
85 * @see BluetoothHidDeviceCallback#onIntrData(byte, byte[])
86 */
87 public static final byte REPORT_TYPE_INPUT = (byte) 1;
88 public static final byte REPORT_TYPE_OUTPUT = (byte) 2;
89 public static final byte REPORT_TYPE_FEATURE = (byte) 3;
90
91 /**
92 * Constants representing error response for Set Report.
93 *
94 * @see BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[])
95 */
96 public static final byte ERROR_RSP_SUCCESS = (byte) 0;
97 public static final byte ERROR_RSP_NOT_READY = (byte) 1;
98 public static final byte ERROR_RSP_INVALID_RPT_ID = (byte) 2;
99 public static final byte ERROR_RSP_UNSUPPORTED_REQ = (byte) 3;
100 public static final byte ERROR_RSP_INVALID_PARAM = (byte) 4;
101 public static final byte ERROR_RSP_UNKNOWN = (byte) 14;
102
103 /**
104 * Constants representing protocol mode used set by host. Default is always
105 * {@link #PROTOCOL_REPORT_MODE} unless notified otherwise.
106 *
107 * @see BluetoothHidDeviceCallback#onSetProtocol(byte)
108 */
109 public static final byte PROTOCOL_BOOT_MODE = (byte) 0;
110 public static final byte PROTOCOL_REPORT_MODE = (byte) 1;
111
112 private Context mContext;
113
114 private ServiceListener mServiceListener;
115
Jack He16eeac32017-08-17 12:11:18 -0700116 private volatile IBluetoothInputHost mService;
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530117
118 private BluetoothAdapter mAdapter;
119
Jack Hea355e5e2017-08-22 16:06:54 -0700120 private static class BluetoothHidDeviceCallbackWrapper extends
121 IBluetoothHidDeviceCallback.Stub {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530122
123 private BluetoothHidDeviceCallback mCallback;
124
125 public BluetoothHidDeviceCallbackWrapper(BluetoothHidDeviceCallback callback) {
126 mCallback = callback;
127 }
128
129 @Override
130 public void onAppStatusChanged(BluetoothDevice pluggedDevice,
131 BluetoothHidDeviceAppConfiguration config, boolean registered) {
132 mCallback.onAppStatusChanged(pluggedDevice, config, registered);
133 }
134
135 @Override
136 public void onConnectionStateChanged(BluetoothDevice device, int state) {
137 mCallback.onConnectionStateChanged(device, state);
138 }
139
140 @Override
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000141 public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
142 mCallback.onGetReport(device, type, id, bufferSize);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530143 }
144
145 @Override
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000146 public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
147 mCallback.onSetReport(device, type, id, data);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530148 }
149
150 @Override
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000151 public void onSetProtocol(BluetoothDevice device, byte protocol) {
152 mCallback.onSetProtocol(device, protocol);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530153 }
154
155 @Override
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000156 public void onIntrData(BluetoothDevice device, byte reportId, byte[] data) {
157 mCallback.onIntrData(device, reportId, data);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530158 }
159
160 @Override
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000161 public void onVirtualCableUnplug(BluetoothDevice device) {
162 mCallback.onVirtualCableUnplug(device);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530163 }
164 }
165
Jack He2992cd02017-08-22 21:21:23 -0700166 private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
Jack Hea355e5e2017-08-22 16:06:54 -0700167 new IBluetoothStateChangeCallback.Stub() {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530168
Jack Hea355e5e2017-08-22 16:06:54 -0700169 public void onBluetoothStateChange(boolean up) {
170 Log.d(TAG, "onBluetoothStateChange: up=" + up);
171 synchronized (mConnection) {
172 if (!up) {
173 Log.d(TAG, "Unbinding service...");
174 if (mService != null) {
175 mService = null;
176 try {
177 mContext.unbindService(mConnection);
178 } catch (IllegalArgumentException e) {
179 Log.e(TAG, "onBluetoothStateChange: could not unbind service:",
180 e);
181 }
182 }
183 } else {
184 try {
185 if (mService == null) {
186 Log.d(TAG, "Binding HID Device service...");
187 doBind();
188 }
189 } catch (IllegalStateException e) {
190 Log.e(TAG,
191 "onBluetoothStateChange: could not bind to HID Dev "
192 + "service: ",
193 e);
194 } catch (SecurityException e) {
195 Log.e(TAG,
196 "onBluetoothStateChange: could not bind to HID Dev "
197 + "service: ",
198 e);
199 }
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530200 }
201 }
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530202 }
Jack Hea355e5e2017-08-22 16:06:54 -0700203 };
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530204
Jack He16eeac32017-08-17 12:11:18 -0700205 private final ServiceConnection mConnection = new ServiceConnection() {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530206 public void onServiceConnected(ComponentName className, IBinder service) {
207 Log.d(TAG, "onServiceConnected()");
Ivan Podogov0afe1902016-12-23 11:52:21 +0000208 mService = IBluetoothInputHost.Stub.asInterface(service);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530209 if (mServiceListener != null) {
Ivan Podogov0afe1902016-12-23 11:52:21 +0000210 mServiceListener.onServiceConnected(BluetoothProfile.INPUT_HOST,
Jack Hea355e5e2017-08-22 16:06:54 -0700211 BluetoothInputHost.this);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530212 }
213 }
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530214 public void onServiceDisconnected(ComponentName className) {
215 Log.d(TAG, "onServiceDisconnected()");
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530216 mService = null;
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530217 if (mServiceListener != null) {
Ivan Podogov0afe1902016-12-23 11:52:21 +0000218 mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_HOST);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530219 }
220 }
221 };
222
Ivan Podogov0afe1902016-12-23 11:52:21 +0000223 BluetoothInputHost(Context context, ServiceListener listener) {
224 Log.v(TAG, "BluetoothInputHost");
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530225
226 mContext = context;
227 mServiceListener = listener;
228 mAdapter = BluetoothAdapter.getDefaultAdapter();
229
230 IBluetoothManager mgr = mAdapter.getBluetoothManager();
231 if (mgr != null) {
232 try {
233 mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
234 } catch (RemoteException e) {
235 e.printStackTrace();
236 }
237 }
238
239 doBind();
240 }
241
242 boolean doBind() {
Ivan Podogov0afe1902016-12-23 11:52:21 +0000243 Intent intent = new Intent(IBluetoothInputHost.class.getName());
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530244 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
245 intent.setComponent(comp);
246 if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
247 android.os.Process.myUserHandle())) {
248 Log.e(TAG, "Could not bind to Bluetooth HID Device Service with " + intent);
249 return false;
250 }
251 Log.d(TAG, "Bound to HID Device Service");
252 return true;
253 }
254
255 void close() {
256 Log.v(TAG, "close()");
257
258 IBluetoothManager mgr = mAdapter.getBluetoothManager();
259 if (mgr != null) {
260 try {
261 mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
262 } catch (RemoteException e) {
263 e.printStackTrace();
264 }
265 }
266
267 synchronized (mConnection) {
268 if (mService != null) {
269 mService = null;
270 try {
271 mContext.unbindService(mConnection);
272 } catch (IllegalArgumentException e) {
Jack Hea355e5e2017-08-22 16:06:54 -0700273 Log.e(TAG, "close: could not unbind HID Dev service: ", e);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530274 }
Jack Hea355e5e2017-08-22 16:06:54 -0700275 }
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530276 }
277
278 mServiceListener = null;
279 }
280
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000281 /**
282 * {@inheritDoc}
283 */
Jack He2992cd02017-08-22 21:21:23 -0700284 @Override
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530285 public List<BluetoothDevice> getConnectedDevices() {
286 Log.v(TAG, "getConnectedDevices()");
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000287
Jack He16eeac32017-08-17 12:11:18 -0700288 final IBluetoothInputHost service = mService;
289 if (service != null) {
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000290 try {
Jack He16eeac32017-08-17 12:11:18 -0700291 return service.getConnectedDevices();
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000292 } catch (RemoteException e) {
293 Log.e(TAG, e.toString());
294 }
295 } else {
296 Log.w(TAG, "Proxy not attached to service");
297 }
298
299 return new ArrayList<BluetoothDevice>();
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530300 }
301
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000302 /**
303 * {@inheritDoc}
304 */
Jack He2992cd02017-08-22 21:21:23 -0700305 @Override
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530306 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
307 Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000308
Jack He16eeac32017-08-17 12:11:18 -0700309 final IBluetoothInputHost service = mService;
310 if (service != null) {
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000311 try {
Jack He16eeac32017-08-17 12:11:18 -0700312 return service.getDevicesMatchingConnectionStates(states);
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000313 } catch (RemoteException e) {
314 Log.e(TAG, e.toString());
315 }
316 } else {
317 Log.w(TAG, "Proxy not attached to service");
318 }
319
320 return new ArrayList<BluetoothDevice>();
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530321 }
322
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000323 /**
324 * {@inheritDoc}
325 */
Jack He2992cd02017-08-22 21:21:23 -0700326 @Override
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530327 public int getConnectionState(BluetoothDevice device) {
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000328 Log.v(TAG, "getConnectionState(): device=" + device);
329
Jack He16eeac32017-08-17 12:11:18 -0700330 final IBluetoothInputHost service = mService;
331 if (service != null) {
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000332 try {
Jack He16eeac32017-08-17 12:11:18 -0700333 return service.getConnectionState(device);
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000334 } catch (RemoteException e) {
335 Log.e(TAG, e.toString());
336 }
337 } else {
338 Log.w(TAG, "Proxy not attached to service");
339 }
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530340
341 return STATE_DISCONNECTED;
342 }
343
344 /**
345 * Registers application to be used for HID device. Connections to HID
346 * Device are only possible when application is registered. Only one
347 * application can be registered at time. When no longer used, application
348 * should be unregistered using
349 * {@link #unregisterApp(BluetoothHidDeviceAppConfiguration)}.
350 *
Jack Hea355e5e2017-08-22 16:06:54 -0700351 * @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of HID Device SDP record.
352 * @param inQos {@link BluetoothHidDeviceAppQosSettings} object of Incoming QoS Settings.
353 * @param outQos {@link BluetoothHidDeviceAppQosSettings} object of Outgoing QoS Settings.
354 * @param callback {@link BluetoothHidDeviceCallback} object to which callback messages will be
355 * sent.
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530356 * @return
357 */
358 public boolean registerApp(BluetoothHidDeviceAppSdpSettings sdp,
359 BluetoothHidDeviceAppQosSettings inQos, BluetoothHidDeviceAppQosSettings outQos,
360 BluetoothHidDeviceCallback callback) {
361 Log.v(TAG, "registerApp(): sdp=" + sdp + " inQos=" + inQos + " outQos=" + outQos
362 + " callback=" + callback);
363
364 boolean result = false;
365
366 if (sdp == null || callback == null) {
367 return false;
368 }
369
Jack He16eeac32017-08-17 12:11:18 -0700370 final IBluetoothInputHost service = mService;
371 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530372 try {
373 BluetoothHidDeviceAppConfiguration config =
Jack Hea355e5e2017-08-22 16:06:54 -0700374 new BluetoothHidDeviceAppConfiguration();
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530375 BluetoothHidDeviceCallbackWrapper cbw =
Jack Hea355e5e2017-08-22 16:06:54 -0700376 new BluetoothHidDeviceCallbackWrapper(callback);
Jack He16eeac32017-08-17 12:11:18 -0700377 result = service.registerApp(config, sdp, inQos, outQos, cbw);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530378 } catch (RemoteException e) {
379 Log.e(TAG, e.toString());
380 }
381 } else {
382 Log.w(TAG, "Proxy not attached to service");
383 }
384
385 return result;
386 }
387
388 /**
389 * Unregisters application. Active connection will be disconnected and no
390 * new connections will be allowed until registered again using
391 * {@link #registerApp(String, String, String, byte, byte[], BluetoothHidDeviceCallback)}
392 *
Jack Hea355e5e2017-08-22 16:06:54 -0700393 * @param config {@link BluetoothHidDeviceAppConfiguration} object as obtained from {@link
394 * BluetoothHidDeviceCallback#onAppStatusChanged(BluetoothDevice,
395 * BluetoothHidDeviceAppConfiguration,
396 * boolean)}
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530397 * @return
398 */
399 public boolean unregisterApp(BluetoothHidDeviceAppConfiguration config) {
400 Log.v(TAG, "unregisterApp()");
401
402 boolean result = false;
403
Jack He16eeac32017-08-17 12:11:18 -0700404 final IBluetoothInputHost service = mService;
405 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530406 try {
Jack He16eeac32017-08-17 12:11:18 -0700407 result = service.unregisterApp(config);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530408 } catch (RemoteException e) {
409 Log.e(TAG, e.toString());
410 }
411 } else {
412 Log.w(TAG, "Proxy not attached to service");
413 }
414
415 return result;
416 }
417
418 /**
419 * Sends report to remote host using interrupt channel.
420 *
Jack Hea355e5e2017-08-22 16:06:54 -0700421 * @param id Report Id, as defined in descriptor. Can be 0 in case Report Id are not defined in
422 * descriptor.
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530423 * @param data Report data, not including Report Id.
424 * @return
425 */
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000426 public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530427 boolean result = false;
428
Jack He16eeac32017-08-17 12:11:18 -0700429 final IBluetoothInputHost service = mService;
430 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530431 try {
Jack He16eeac32017-08-17 12:11:18 -0700432 result = service.sendReport(device, id, data);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530433 } catch (RemoteException e) {
434 Log.e(TAG, e.toString());
435 }
436 } else {
437 Log.w(TAG, "Proxy not attached to service");
438 }
439
440 return result;
441 }
442
443 /**
444 * Sends report to remote host as reply for GET_REPORT request from
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000445 * {@link BluetoothHidDeviceCallback#onGetReport(BluetoothDevice, byte, byte, int)}.
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530446 *
447 * @param type Report Type, as in request.
448 * @param id Report Id, as in request.
449 * @param data Report data, not including Report Id.
450 * @return
451 */
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000452 public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {
453 Log.v(TAG, "replyReport(): device=" + device + " type=" + type + " id=" + id);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530454
455 boolean result = false;
456
Jack He16eeac32017-08-17 12:11:18 -0700457 final IBluetoothInputHost service = mService;
458 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530459 try {
Jack He16eeac32017-08-17 12:11:18 -0700460 result = service.replyReport(device, type, id, data);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530461 } catch (RemoteException e) {
462 Log.e(TAG, e.toString());
463 }
464 } else {
465 Log.w(TAG, "Proxy not attached to service");
466 }
467
468 return result;
469 }
470
471 /**
472 * Sends error handshake message as reply for invalid SET_REPORT request
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000473 * from {@link BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])}.
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530474 *
475 * @param error Error to be sent for SET_REPORT via HANDSHAKE.
476 * @return
477 */
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000478 public boolean reportError(BluetoothDevice device, byte error) {
479 Log.v(TAG, "reportError(): device=" + device + " error=" + error);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530480
481 boolean result = false;
482
Jack He16eeac32017-08-17 12:11:18 -0700483 final IBluetoothInputHost service = mService;
484 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530485 try {
Jack He16eeac32017-08-17 12:11:18 -0700486 result = service.reportError(device, error);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530487 } catch (RemoteException e) {
488 Log.e(TAG, e.toString());
489 }
490 } else {
491 Log.w(TAG, "Proxy not attached to service");
492 }
493
494 return result;
495 }
496
497 /**
498 * Sends Virtual Cable Unplug to currently connected host.
499 *
500 * @return
501 */
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000502 public boolean unplug(BluetoothDevice device) {
503 Log.v(TAG, "unplug(): device=" + device);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530504
505 boolean result = false;
506
Jack He16eeac32017-08-17 12:11:18 -0700507 final IBluetoothInputHost service = mService;
508 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530509 try {
Jack He16eeac32017-08-17 12:11:18 -0700510 result = service.unplug(device);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530511 } catch (RemoteException e) {
512 Log.e(TAG, e.toString());
513 }
514 } else {
515 Log.w(TAG, "Proxy not attached to service");
516 }
517
518 return result;
519 }
520
521 /**
522 * Initiates connection to host which currently has Virtual Cable
523 * established with device.
524 *
525 * @return
526 */
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000527 public boolean connect(BluetoothDevice device) {
528 Log.v(TAG, "connect(): device=" + device);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530529
530 boolean result = false;
531
Jack He16eeac32017-08-17 12:11:18 -0700532 final IBluetoothInputHost service = mService;
533 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530534 try {
Jack He16eeac32017-08-17 12:11:18 -0700535 result = service.connect(device);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530536 } catch (RemoteException e) {
537 Log.e(TAG, e.toString());
538 }
539 } else {
540 Log.w(TAG, "Proxy not attached to service");
541 }
542
543 return result;
544 }
545
546 /**
547 * Disconnects from currently connected host.
548 *
549 * @return
550 */
Ivan Podogovdd87cd32016-12-30 14:43:29 +0000551 public boolean disconnect(BluetoothDevice device) {
552 Log.v(TAG, "disconnect(): device=" + device);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530553
554 boolean result = false;
555
Jack He16eeac32017-08-17 12:11:18 -0700556 final IBluetoothInputHost service = mService;
557 if (service != null) {
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530558 try {
Jack He16eeac32017-08-17 12:11:18 -0700559 result = service.disconnect(device);
Hemant Guptae88fd4b2014-04-18 11:22:45 +0530560 } catch (RemoteException e) {
561 Log.e(TAG, e.toString());
562 }
563 } else {
564 Log.w(TAG, "Proxy not attached to service");
565 }
566
567 return result;
568 }
569}