blob: b8b8f5fa92c3384601ed3f86eccc778be95b4eaa [file] [log] [blame]
Jaikumar Ganesh545e6702010-06-04 10:23:03 -07001/*
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -08002 * Copyright (C) 2011 The Android Open Source Project
Jaikumar Ganesh545e6702010-06-04 10:23:03 -07003 *
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
19import android.annotation.SdkConstant;
20import android.annotation.SdkConstant.SdkConstantType;
Matthew Xiebf246ef2012-03-21 23:15:06 -070021import android.content.ComponentName;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070022import android.content.Context;
Matthew Xiebf246ef2012-03-21 23:15:06 -070023import android.content.Intent;
24import android.content.ServiceConnection;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070025import android.os.IBinder;
26import android.os.RemoteException;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070027import android.util.Log;
28
Jaikumar Ganesh5a1e4cf2010-10-18 17:05:09 -070029import java.util.ArrayList;
30import java.util.List;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070031
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080032
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070033/**
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080034 * This class provides the public APIs to control the Bluetooth Input
35 * Device Profile.
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070036 *
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080037 *<p>BluetoothInputDevice is a proxy object for controlling the Bluetooth
38 * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
39 * the BluetoothInputDevice proxy object.
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070040 *
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080041 *<p>Each method is protected with its appropriate permission.
42 *@hide
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070043 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080044public final class BluetoothInputDevice implements BluetoothProfile {
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070045 private static final String TAG = "BluetoothInputDevice";
fredc0f420372012-04-12 00:02:00 -070046 private static final boolean DBG = true;
Matthew Xie563e4142012-10-09 22:10:37 -070047 private static final boolean VDBG = false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070048
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080049 /**
50 * Intent used to broadcast the change in connection state of the Input
51 * Device profile.
52 *
53 * <p>This intent will have 3 extras:
54 * <ul>
55 * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
56 * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
57 * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
58 * </ul>
59 *
60 * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
61 * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
62 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
63 *
64 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
65 * receive.
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070066 */
67 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080068 public static final String ACTION_CONNECTION_STATE_CHANGED =
69 "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070070
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -080071 /**
Priti Aghera349e62f2012-04-09 12:13:17 -070072 * @hide
73 */
74 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
75 public static final String ACTION_PROTOCOL_MODE_CHANGED =
76 "android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED";
77
Mike J. Chend96d5cf2014-01-27 17:55:40 -080078 /**
79 * @hide
80 */
81 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
82 public static final String ACTION_REPORT =
83 "android.bluetooth.input.profile.action.REPORT";
Priti Aghera349e62f2012-04-09 12:13:17 -070084
85 /**
86 * @hide
87 */
88 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
89 public static final String ACTION_VIRTUAL_UNPLUG_STATUS =
90 "android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS";
91
92
93 /**
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -080094 * Return codes for the connect and disconnect Bluez / Dbus calls.
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080095 * @hide
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -080096 */
97 public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000;
98
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080099 /**
100 * @hide
101 */
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -0800102 public static final int INPUT_CONNECT_FAILED_ALREADY_CONNECTED = 5001;
103
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800104 /**
105 * @hide
106 */
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -0800107 public static final int INPUT_CONNECT_FAILED_ATTEMPT_FAILED = 5002;
108
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800109 /**
110 * @hide
111 */
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -0800112 public static final int INPUT_OPERATION_GENERIC_FAILURE = 5003;
113
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800114 /**
115 * @hide
116 */
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -0800117 public static final int INPUT_OPERATION_SUCCESS = 5004;
118
Priti Aghera349e62f2012-04-09 12:13:17 -0700119 /**
120 * @hide
121 */
122 public static final int PROTOCOL_REPORT_MODE = 0;
123
124 /**
125 * @hide
126 */
127 public static final int PROTOCOL_BOOT_MODE = 1;
128
129 /**
130 * @hide
131 */
132 public static final int PROTOCOL_UNSUPPORTED_MODE = 255;
133
134 /* int reportType, int reportType, int bufferSize */
135 /**
136 * @hide
137 */
Mike J. Chen1b47f7c2014-01-27 16:27:04 -0800138 public static final byte REPORT_TYPE_INPUT = 1;
Priti Aghera349e62f2012-04-09 12:13:17 -0700139
140 /**
141 * @hide
142 */
Mike J. Chen1b47f7c2014-01-27 16:27:04 -0800143 public static final byte REPORT_TYPE_OUTPUT = 2;
Priti Aghera349e62f2012-04-09 12:13:17 -0700144
145 /**
146 * @hide
147 */
Mike J. Chen1b47f7c2014-01-27 16:27:04 -0800148 public static final byte REPORT_TYPE_FEATURE = 3;
Priti Aghera349e62f2012-04-09 12:13:17 -0700149
150 /**
151 * @hide
152 */
153 public static final int VIRTUAL_UNPLUG_STATUS_SUCCESS = 0;
154
155 /**
156 * @hide
157 */
158 public static final int VIRTUAL_UNPLUG_STATUS_FAIL = 1;
159
160 /**
161 * @hide
162 */
163 public static final String EXTRA_PROTOCOL_MODE = "android.bluetooth.BluetoothInputDevice.extra.PROTOCOL_MODE";
164
165 /**
166 * @hide
167 */
168 public static final String EXTRA_REPORT_TYPE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_TYPE";
169
170 /**
171 * @hide
172 */
173 public static final String EXTRA_REPORT_ID = "android.bluetooth.BluetoothInputDevice.extra.REPORT_ID";
174
175 /**
176 * @hide
177 */
178 public static final String EXTRA_REPORT_BUFFER_SIZE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_BUFFER_SIZE";
179
180 /**
181 * @hide
182 */
183 public static final String EXTRA_REPORT = "android.bluetooth.BluetoothInputDevice.extra.REPORT";
184
185 /**
186 * @hide
187 */
188 public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS";
189
Matthew Xiebf246ef2012-03-21 23:15:06 -0700190 private Context mContext;
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800191 private ServiceListener mServiceListener;
192 private BluetoothAdapter mAdapter;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700193 private IBluetoothInputDevice mService;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700194
fredc0f420372012-04-12 00:02:00 -0700195 final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
196 new IBluetoothStateChangeCallback.Stub() {
197 public void onBluetoothStateChange(boolean up) {
198 if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
199 if (!up) {
Matthew Xie563e4142012-10-09 22:10:37 -0700200 if (VDBG) Log.d(TAG,"Unbinding service...");
fredc0f420372012-04-12 00:02:00 -0700201 synchronized (mConnection) {
202 try {
203 mService = null;
204 mContext.unbindService(mConnection);
205 } catch (Exception re) {
206 Log.e(TAG,"",re);
207 }
208 }
209 } else {
210 synchronized (mConnection) {
211 try {
212 if (mService == null) {
Matthew Xie563e4142012-10-09 22:10:37 -0700213 if (VDBG) Log.d(TAG,"Binding service...");
Dianne Hackborn221ea892013-08-04 16:50:16 -0700214 doBind();
fredc0f420372012-04-12 00:02:00 -0700215 }
216 } catch (Exception re) {
217 Log.e(TAG,"",re);
218 }
219 }
220 }
221 }
222 };
223
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700224 /**
225 * Create a BluetoothInputDevice proxy object for interacting with the local
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800226 * Bluetooth Service which handles the InputDevice profile
227 *
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700228 */
Matthew Xiebf246ef2012-03-21 23:15:06 -0700229 /*package*/ BluetoothInputDevice(Context context, ServiceListener l) {
230 mContext = context;
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800231 mServiceListener = l;
232 mAdapter = BluetoothAdapter.getDefaultAdapter();
fredc0f420372012-04-12 00:02:00 -0700233
234 IBluetoothManager mgr = mAdapter.getBluetoothManager();
235 if (mgr != null) {
236 try {
237 mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
238 } catch (RemoteException e) {
239 Log.e(TAG,"",e);
240 }
241 }
242
Dianne Hackborn221ea892013-08-04 16:50:16 -0700243 doBind();
244 }
245
246 boolean doBind() {
247 Intent intent = new Intent(IBluetoothInputDevice.class.getName());
248 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
249 intent.setComponent(comp);
250 if (comp == null || !mContext.bindService(intent, mConnection, 0)) {
251 Log.e(TAG, "Could not bind to Bluetooth HID Service with " + intent);
252 return false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700253 }
Dianne Hackborn221ea892013-08-04 16:50:16 -0700254 return true;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700255 }
256
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800257 /*package*/ void close() {
Matthew Xie563e4142012-10-09 22:10:37 -0700258 if (VDBG) log("close()");
fredc0f420372012-04-12 00:02:00 -0700259 IBluetoothManager mgr = mAdapter.getBluetoothManager();
260 if (mgr != null) {
261 try {
262 mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
263 } catch (Exception e) {
264 Log.e(TAG,"",e);
265 }
266 }
267
268 synchronized (mConnection) {
269 if (mService != null) {
270 try {
271 mService = null;
272 mContext.unbindService(mConnection);
273 } catch (Exception re) {
274 Log.e(TAG,"",re);
275 }
276 }
Matthew Xiebf246ef2012-03-21 23:15:06 -0700277 }
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800278 mServiceListener = null;
279 }
280
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800281 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700282 * Initiate connection to a profile of the remote bluetooth device.
283 *
284 * <p> The system supports connection to multiple input devices.
285 *
286 * <p> This API returns false in scenarios like the profile on the
287 * device is already connected or Bluetooth is not turned on.
288 * When this API returns true, it is guaranteed that
289 * connection state intent for the profile will be broadcasted with
290 * the state. Users can get the connection state of the profile
291 * from this intent.
292 *
293 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
294 * permission.
295 *
296 * @param device Remote Bluetooth Device
297 * @return false on immediate error,
298 * true otherwise
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800299 * @hide
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700300 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800301 public boolean connect(BluetoothDevice device) {
302 if (DBG) log("connect(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700303 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800304 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700305 return mService.connect(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800306 } catch (RemoteException e) {
307 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
308 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700309 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700310 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800311 if (mService == null) Log.w(TAG, "Proxy not attached to service");
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700312 return false;
313 }
314
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800315 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700316 * Initiate disconnection from a profile
317 *
318 * <p> This API will return false in scenarios like the profile on the
319 * Bluetooth device is not in connected state etc. When this API returns,
320 * true, it is guaranteed that the connection state change
321 * intent will be broadcasted with the state. Users can get the
322 * disconnection state of the profile from this intent.
323 *
324 * <p> If the disconnection is initiated by a remote device, the state
325 * will transition from {@link #STATE_CONNECTED} to
326 * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
327 * host (local) device the state will transition from
328 * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
329 * state {@link #STATE_DISCONNECTED}. The transition to
330 * {@link #STATE_DISCONNECTING} can be used to distinguish between the
331 * two scenarios.
332 *
333 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
334 * permission.
335 *
336 * @param device Remote Bluetooth Device
337 * @return false on immediate error,
338 * true otherwise
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700339 * @hide
340 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800341 public boolean disconnect(BluetoothDevice device) {
342 if (DBG) log("disconnect(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700343 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800344 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700345 return mService.disconnect(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800346 } catch (RemoteException e) {
347 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
348 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700349 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700350 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800351 if (mService == null) Log.w(TAG, "Proxy not attached to service");
352 return false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700353 }
354
355 /**
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800356 * {@inheritDoc}
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700357 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800358 public List<BluetoothDevice> getConnectedDevices() {
Matthew Xie563e4142012-10-09 22:10:37 -0700359 if (VDBG) log("getConnectedDevices()");
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800360 if (mService != null && isEnabled()) {
361 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700362 return mService.getConnectedDevices();
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800363 } catch (RemoteException e) {
364 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
365 return new ArrayList<BluetoothDevice>();
Matthew Xiebf246ef2012-03-21 23:15:06 -0700366 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700367 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800368 if (mService == null) Log.w(TAG, "Proxy not attached to service");
369 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700370 }
371
372 /**
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800373 * {@inheritDoc}
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700374 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800375 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Matthew Xie563e4142012-10-09 22:10:37 -0700376 if (VDBG) log("getDevicesMatchingStates()");
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800377 if (mService != null && isEnabled()) {
378 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700379 return mService.getDevicesMatchingConnectionStates(states);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800380 } catch (RemoteException e) {
381 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
382 return new ArrayList<BluetoothDevice>();
Matthew Xiebf246ef2012-03-21 23:15:06 -0700383 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700384 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800385 if (mService == null) Log.w(TAG, "Proxy not attached to service");
386 return new ArrayList<BluetoothDevice>();
387 }
388
389 /**
390 * {@inheritDoc}
391 */
392 public int getConnectionState(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700393 if (VDBG) log("getState(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700394 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800395 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700396 return mService.getConnectionState(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800397 } catch (RemoteException e) {
398 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
399 return BluetoothProfile.STATE_DISCONNECTED;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700400 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800401 }
402 if (mService == null) Log.w(TAG, "Proxy not attached to service");
403 return BluetoothProfile.STATE_DISCONNECTED;
404 }
405
406 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700407 * Set priority of the profile
408 *
409 * <p> The device should already be paired.
410 * Priority can be one of {@link #PRIORITY_ON} or
411 * {@link #PRIORITY_OFF},
412 *
413 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
414 * permission.
415 *
416 * @param device Paired bluetooth device
417 * @param priority
418 * @return true if priority is set, false on error
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800419 * @hide
420 */
421 public boolean setPriority(BluetoothDevice device, int priority) {
422 if (DBG) log("setPriority(" + device + ", " + priority + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700423 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800424 if (priority != BluetoothProfile.PRIORITY_OFF &&
425 priority != BluetoothProfile.PRIORITY_ON) {
426 return false;
427 }
428 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700429 return mService.setPriority(device, priority);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800430 } catch (RemoteException e) {
431 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
432 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700433 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800434 }
435 if (mService == null) Log.w(TAG, "Proxy not attached to service");
436 return false;
437 }
438
439 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700440 * Get the priority of the profile.
441 *
442 * <p> The priority can be any of:
443 * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
444 * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
445 *
446 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
447 *
448 * @param device Bluetooth device
449 * @return priority of the device
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800450 * @hide
451 */
452 public int getPriority(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700453 if (VDBG) log("getPriority(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700454 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800455 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700456 return mService.getPriority(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800457 } catch (RemoteException e) {
458 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
459 return BluetoothProfile.PRIORITY_OFF;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700460 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800461 }
462 if (mService == null) Log.w(TAG, "Proxy not attached to service");
463 return BluetoothProfile.PRIORITY_OFF;
464 }
465
Matthew Xie9b693992013-10-10 11:21:40 -0700466 private final ServiceConnection mConnection = new ServiceConnection() {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700467 public void onServiceConnected(ComponentName className, IBinder service) {
468 if (DBG) Log.d(TAG, "Proxy object connected");
469 mService = IBluetoothInputDevice.Stub.asInterface(service);
470
471 if (mServiceListener != null) {
472 mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, BluetoothInputDevice.this);
473 }
474 }
475 public void onServiceDisconnected(ComponentName className) {
476 if (DBG) Log.d(TAG, "Proxy object disconnected");
477 mService = null;
478 if (mServiceListener != null) {
479 mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_DEVICE);
480 }
481 }
482 };
483
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800484 private boolean isEnabled() {
485 if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
486 return false;
487 }
488
489 private boolean isValidDevice(BluetoothDevice device) {
490 if (device == null) return false;
491
492 if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
493 return false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700494 }
495
Priti Aghera349e62f2012-04-09 12:13:17 -0700496
497 /**
498 * Initiate virtual unplug for a HID input device.
499 *
500 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
501 *
502 * @param device Remote Bluetooth Device
503 * @return false on immediate error,
504 * true otherwise
505 * @hide
506 */
507 public boolean virtualUnplug(BluetoothDevice device) {
508 if (DBG) log("virtualUnplug(" + device + ")");
509 if (mService != null && isEnabled() && isValidDevice(device)) {
510 try {
511 return mService.virtualUnplug(device);
512 } catch (RemoteException e) {
513 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
514 return false;
515 }
516 }
517
518 if (mService == null) Log.w(TAG, "Proxy not attached to service");
519 return false;
520
521 }
522
523 /**
524 * Send Get_Protocol_Mode command to the connected HID input device.
525 *
526 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
527 *
528 * @param device Remote Bluetooth Device
529 * @return false on immediate error,
530 *true otherwise
531 * @hide
532 */
533 public boolean getProtocolMode(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700534 if (VDBG) log("getProtocolMode(" + device + ")");
Priti Aghera349e62f2012-04-09 12:13:17 -0700535 if (mService != null && isEnabled() && isValidDevice(device)) {
536 try {
537 return mService.getProtocolMode(device);
538 } catch (RemoteException e) {
539 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
540 return false;
541 }
542 }
543 if (mService == null) Log.w(TAG, "Proxy not attached to service");
544 return false;
545 }
546
547 /**
548 * Send Set_Protocol_Mode command to the connected HID input device.
549 *
550 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
551 *
552 * @param device Remote Bluetooth Device
553 * @return false on immediate error,
554 * true otherwise
555 * @hide
556 */
557 public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
558 if (DBG) log("setProtocolMode(" + device + ")");
559 if (mService != null && isEnabled() && isValidDevice(device)) {
560 try {
561 return mService.setProtocolMode(device, protocolMode);
562 } catch (RemoteException e) {
563 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
564 return false;
565 }
566 }
567 if (mService == null) Log.w(TAG, "Proxy not attached to service");
568 return false;
569 }
570
571 /**
572 * Send Get_Report command to the connected HID input device.
573 *
574 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
575 *
576 * @param device Remote Bluetooth Device
577 * @param reportType Report type
578 * @param reportId Report ID
579 * @param bufferSize Report receiving buffer size
580 * @return false on immediate error,
581 * true otherwise
582 * @hide
583 */
584 public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) {
Matthew Xie563e4142012-10-09 22:10:37 -0700585 if (VDBG) log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId + "bufferSize=" + bufferSize);
Priti Aghera349e62f2012-04-09 12:13:17 -0700586 if (mService != null && isEnabled() && isValidDevice(device)) {
587 try {
588 return mService.getReport(device, reportType, reportId, bufferSize);
589 } catch (RemoteException e) {
590 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
591 return false;
592 }
593 }
594 if (mService == null) Log.w(TAG, "Proxy not attached to service");
595 return false;
596 }
597
598 /**
599 * Send Set_Report command to the connected HID input device.
600 *
601 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
602 *
603 * @param device Remote Bluetooth Device
604 * @param reportType Report type
605 * @param report Report receiving buffer size
606 * @return false on immediate error,
607 * true otherwise
608 * @hide
609 */
610 public boolean setReport(BluetoothDevice device, byte reportType, String report) {
611 if (DBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
612 if (mService != null && isEnabled() && isValidDevice(device)) {
613 try {
614 return mService.setReport(device, reportType, report);
615 } catch (RemoteException e) {
616 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
617 return false;
618 }
619 }
620 if (mService == null) Log.w(TAG, "Proxy not attached to service");
621 return false;
622 }
623
624 /**
625 * Send Send_Data command to the connected HID input device.
626 *
627 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
628 *
629 * @param device Remote Bluetooth Device
630 * @param data Data to send
631 * @return false on immediate error,
632 * true otherwise
633 * @hide
634 */
635 public boolean sendData(BluetoothDevice device, String report) {
636 if (DBG) log("sendData(" + device + "), report=" + report);
637 if (mService != null && isEnabled() && isValidDevice(device)) {
638 try {
639 return mService.sendData(device, report);
640 } catch (RemoteException e) {
641 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
642 return false;
643 }
644 }
645 if (mService == null) Log.w(TAG, "Proxy not attached to service");
646 return false;
647 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700648 private static void log(String msg) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800649 Log.d(TAG, msg);
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700650 }
651}