blob: bc3ad443d35e8112f319e2178aa499b64df695e3 [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;
Priti Aghera349e62f2012-04-09 12:13:17 -070027import android.os.ServiceManager;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070028import android.util.Log;
29
Jaikumar Ganesh5a1e4cf2010-10-18 17:05:09 -070030import java.util.ArrayList;
31import java.util.List;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070032
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080033
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070034/**
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080035 * This class provides the public APIs to control the Bluetooth Input
36 * Device Profile.
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070037 *
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080038 *<p>BluetoothInputDevice is a proxy object for controlling the Bluetooth
39 * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
40 * the BluetoothInputDevice proxy object.
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070041 *
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080042 *<p>Each method is protected with its appropriate permission.
43 *@hide
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070044 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080045public final class BluetoothInputDevice implements BluetoothProfile {
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070046 private static final String TAG = "BluetoothInputDevice";
fredc0f420372012-04-12 00:02:00 -070047 private static final boolean DBG = true;
Matthew Xie563e4142012-10-09 22:10:37 -070048 private static final boolean VDBG = false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070049
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080050 /**
51 * Intent used to broadcast the change in connection state of the Input
52 * Device profile.
53 *
54 * <p>This intent will have 3 extras:
55 * <ul>
56 * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
57 * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
58 * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
59 * </ul>
60 *
61 * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
62 * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
63 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
64 *
65 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
66 * receive.
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070067 */
68 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080069 public static final String ACTION_CONNECTION_STATE_CHANGED =
70 "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070071
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -080072 /**
Priti Aghera349e62f2012-04-09 12:13:17 -070073 * @hide
74 */
75 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
76 public static final String ACTION_PROTOCOL_MODE_CHANGED =
77 "android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED";
78
79
80 /**
81 * @hide
82 */
83 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
84 public static final String ACTION_VIRTUAL_UNPLUG_STATUS =
85 "android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS";
86
87
88 /**
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -080089 * Return codes for the connect and disconnect Bluez / Dbus calls.
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080090 * @hide
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -080091 */
92 public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000;
93
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080094 /**
95 * @hide
96 */
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -080097 public static final int INPUT_CONNECT_FAILED_ALREADY_CONNECTED = 5001;
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_ATTEMPT_FAILED = 5002;
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_OPERATION_GENERIC_FAILURE = 5003;
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_SUCCESS = 5004;
113
Priti Aghera349e62f2012-04-09 12:13:17 -0700114 /**
115 * @hide
116 */
117 public static final int PROTOCOL_REPORT_MODE = 0;
118
119 /**
120 * @hide
121 */
122 public static final int PROTOCOL_BOOT_MODE = 1;
123
124 /**
125 * @hide
126 */
127 public static final int PROTOCOL_UNSUPPORTED_MODE = 255;
128
129 /* int reportType, int reportType, int bufferSize */
130 /**
131 * @hide
132 */
Mike J. Chen1b47f7c2014-01-27 16:27:04 -0800133 public static final byte REPORT_TYPE_INPUT = 1;
Priti Aghera349e62f2012-04-09 12:13:17 -0700134
135 /**
136 * @hide
137 */
Mike J. Chen1b47f7c2014-01-27 16:27:04 -0800138 public static final byte REPORT_TYPE_OUTPUT = 2;
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_FEATURE = 3;
Priti Aghera349e62f2012-04-09 12:13:17 -0700144
145 /**
146 * @hide
147 */
148 public static final int VIRTUAL_UNPLUG_STATUS_SUCCESS = 0;
149
150 /**
151 * @hide
152 */
153 public static final int VIRTUAL_UNPLUG_STATUS_FAIL = 1;
154
155 /**
156 * @hide
157 */
158 public static final String EXTRA_PROTOCOL_MODE = "android.bluetooth.BluetoothInputDevice.extra.PROTOCOL_MODE";
159
160 /**
161 * @hide
162 */
163 public static final String EXTRA_REPORT_TYPE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_TYPE";
164
165 /**
166 * @hide
167 */
168 public static final String EXTRA_REPORT_ID = "android.bluetooth.BluetoothInputDevice.extra.REPORT_ID";
169
170 /**
171 * @hide
172 */
173 public static final String EXTRA_REPORT_BUFFER_SIZE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_BUFFER_SIZE";
174
175 /**
176 * @hide
177 */
178 public static final String EXTRA_REPORT = "android.bluetooth.BluetoothInputDevice.extra.REPORT";
179
180 /**
181 * @hide
182 */
183 public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS";
184
Matthew Xiebf246ef2012-03-21 23:15:06 -0700185 private Context mContext;
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800186 private ServiceListener mServiceListener;
187 private BluetoothAdapter mAdapter;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700188 private IBluetoothInputDevice mService;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700189
fredc0f420372012-04-12 00:02:00 -0700190 final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
191 new IBluetoothStateChangeCallback.Stub() {
192 public void onBluetoothStateChange(boolean up) {
193 if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
194 if (!up) {
Matthew Xie563e4142012-10-09 22:10:37 -0700195 if (VDBG) Log.d(TAG,"Unbinding service...");
fredc0f420372012-04-12 00:02:00 -0700196 synchronized (mConnection) {
197 try {
198 mService = null;
199 mContext.unbindService(mConnection);
200 } catch (Exception re) {
201 Log.e(TAG,"",re);
202 }
203 }
204 } else {
205 synchronized (mConnection) {
206 try {
207 if (mService == null) {
Matthew Xie563e4142012-10-09 22:10:37 -0700208 if (VDBG) Log.d(TAG,"Binding service...");
Dianne Hackborn221ea892013-08-04 16:50:16 -0700209 doBind();
fredc0f420372012-04-12 00:02:00 -0700210 }
211 } catch (Exception re) {
212 Log.e(TAG,"",re);
213 }
214 }
215 }
216 }
217 };
218
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700219 /**
220 * Create a BluetoothInputDevice proxy object for interacting with the local
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800221 * Bluetooth Service which handles the InputDevice profile
222 *
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700223 */
Matthew Xiebf246ef2012-03-21 23:15:06 -0700224 /*package*/ BluetoothInputDevice(Context context, ServiceListener l) {
225 mContext = context;
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800226 mServiceListener = l;
227 mAdapter = BluetoothAdapter.getDefaultAdapter();
fredc0f420372012-04-12 00:02:00 -0700228
229 IBluetoothManager mgr = mAdapter.getBluetoothManager();
230 if (mgr != null) {
231 try {
232 mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
233 } catch (RemoteException e) {
234 Log.e(TAG,"",e);
235 }
236 }
237
Dianne Hackborn221ea892013-08-04 16:50:16 -0700238 doBind();
239 }
240
241 boolean doBind() {
242 Intent intent = new Intent(IBluetoothInputDevice.class.getName());
243 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
244 intent.setComponent(comp);
245 if (comp == null || !mContext.bindService(intent, mConnection, 0)) {
246 Log.e(TAG, "Could not bind to Bluetooth HID Service with " + intent);
247 return false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700248 }
Dianne Hackborn221ea892013-08-04 16:50:16 -0700249 return true;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700250 }
251
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800252 /*package*/ void close() {
Matthew Xie563e4142012-10-09 22:10:37 -0700253 if (VDBG) log("close()");
fredc0f420372012-04-12 00:02:00 -0700254 IBluetoothManager mgr = mAdapter.getBluetoothManager();
255 if (mgr != null) {
256 try {
257 mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
258 } catch (Exception e) {
259 Log.e(TAG,"",e);
260 }
261 }
262
263 synchronized (mConnection) {
264 if (mService != null) {
265 try {
266 mService = null;
267 mContext.unbindService(mConnection);
268 } catch (Exception re) {
269 Log.e(TAG,"",re);
270 }
271 }
Matthew Xiebf246ef2012-03-21 23:15:06 -0700272 }
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800273 mServiceListener = null;
274 }
275
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800276 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700277 * Initiate connection to a profile of the remote bluetooth device.
278 *
279 * <p> The system supports connection to multiple input devices.
280 *
281 * <p> This API returns false in scenarios like the profile on the
282 * device is already connected or Bluetooth is not turned on.
283 * When this API returns true, it is guaranteed that
284 * connection state intent for the profile will be broadcasted with
285 * the state. Users can get the connection state of the profile
286 * from this intent.
287 *
288 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
289 * permission.
290 *
291 * @param device Remote Bluetooth Device
292 * @return false on immediate error,
293 * true otherwise
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800294 * @hide
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700295 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800296 public boolean connect(BluetoothDevice device) {
297 if (DBG) log("connect(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700298 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800299 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700300 return mService.connect(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800301 } catch (RemoteException e) {
302 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
303 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700304 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700305 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800306 if (mService == null) Log.w(TAG, "Proxy not attached to service");
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700307 return false;
308 }
309
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800310 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700311 * Initiate disconnection from a profile
312 *
313 * <p> This API will return false in scenarios like the profile on the
314 * Bluetooth device is not in connected state etc. When this API returns,
315 * true, it is guaranteed that the connection state change
316 * intent will be broadcasted with the state. Users can get the
317 * disconnection state of the profile from this intent.
318 *
319 * <p> If the disconnection is initiated by a remote device, the state
320 * will transition from {@link #STATE_CONNECTED} to
321 * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
322 * host (local) device the state will transition from
323 * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
324 * state {@link #STATE_DISCONNECTED}. The transition to
325 * {@link #STATE_DISCONNECTING} can be used to distinguish between the
326 * two scenarios.
327 *
328 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
329 * permission.
330 *
331 * @param device Remote Bluetooth Device
332 * @return false on immediate error,
333 * true otherwise
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700334 * @hide
335 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800336 public boolean disconnect(BluetoothDevice device) {
337 if (DBG) log("disconnect(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700338 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800339 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700340 return mService.disconnect(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800341 } catch (RemoteException e) {
342 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
343 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700344 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700345 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800346 if (mService == null) Log.w(TAG, "Proxy not attached to service");
347 return false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700348 }
349
350 /**
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800351 * {@inheritDoc}
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700352 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800353 public List<BluetoothDevice> getConnectedDevices() {
Matthew Xie563e4142012-10-09 22:10:37 -0700354 if (VDBG) log("getConnectedDevices()");
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800355 if (mService != null && isEnabled()) {
356 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700357 return mService.getConnectedDevices();
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800358 } catch (RemoteException e) {
359 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
360 return new ArrayList<BluetoothDevice>();
Matthew Xiebf246ef2012-03-21 23:15:06 -0700361 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700362 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800363 if (mService == null) Log.w(TAG, "Proxy not attached to service");
364 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700365 }
366
367 /**
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800368 * {@inheritDoc}
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700369 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800370 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Matthew Xie563e4142012-10-09 22:10:37 -0700371 if (VDBG) log("getDevicesMatchingStates()");
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800372 if (mService != null && isEnabled()) {
373 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700374 return mService.getDevicesMatchingConnectionStates(states);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800375 } catch (RemoteException e) {
376 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
377 return new ArrayList<BluetoothDevice>();
Matthew Xiebf246ef2012-03-21 23:15:06 -0700378 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700379 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800380 if (mService == null) Log.w(TAG, "Proxy not attached to service");
381 return new ArrayList<BluetoothDevice>();
382 }
383
384 /**
385 * {@inheritDoc}
386 */
387 public int getConnectionState(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700388 if (VDBG) log("getState(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700389 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800390 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700391 return mService.getConnectionState(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800392 } catch (RemoteException e) {
393 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
394 return BluetoothProfile.STATE_DISCONNECTED;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700395 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800396 }
397 if (mService == null) Log.w(TAG, "Proxy not attached to service");
398 return BluetoothProfile.STATE_DISCONNECTED;
399 }
400
401 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700402 * Set priority of the profile
403 *
404 * <p> The device should already be paired.
405 * Priority can be one of {@link #PRIORITY_ON} or
406 * {@link #PRIORITY_OFF},
407 *
408 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
409 * permission.
410 *
411 * @param device Paired bluetooth device
412 * @param priority
413 * @return true if priority is set, false on error
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800414 * @hide
415 */
416 public boolean setPriority(BluetoothDevice device, int priority) {
417 if (DBG) log("setPriority(" + device + ", " + priority + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700418 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800419 if (priority != BluetoothProfile.PRIORITY_OFF &&
420 priority != BluetoothProfile.PRIORITY_ON) {
421 return false;
422 }
423 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700424 return mService.setPriority(device, priority);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800425 } catch (RemoteException e) {
426 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
427 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700428 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800429 }
430 if (mService == null) Log.w(TAG, "Proxy not attached to service");
431 return false;
432 }
433
434 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700435 * Get the priority of the profile.
436 *
437 * <p> The priority can be any of:
438 * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
439 * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
440 *
441 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
442 *
443 * @param device Bluetooth device
444 * @return priority of the device
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800445 * @hide
446 */
447 public int getPriority(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700448 if (VDBG) log("getPriority(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700449 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800450 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700451 return mService.getPriority(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800452 } catch (RemoteException e) {
453 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
454 return BluetoothProfile.PRIORITY_OFF;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700455 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800456 }
457 if (mService == null) Log.w(TAG, "Proxy not attached to service");
458 return BluetoothProfile.PRIORITY_OFF;
459 }
460
Matthew Xie9b693992013-10-10 11:21:40 -0700461 private final ServiceConnection mConnection = new ServiceConnection() {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700462 public void onServiceConnected(ComponentName className, IBinder service) {
463 if (DBG) Log.d(TAG, "Proxy object connected");
464 mService = IBluetoothInputDevice.Stub.asInterface(service);
465
466 if (mServiceListener != null) {
467 mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, BluetoothInputDevice.this);
468 }
469 }
470 public void onServiceDisconnected(ComponentName className) {
471 if (DBG) Log.d(TAG, "Proxy object disconnected");
472 mService = null;
473 if (mServiceListener != null) {
474 mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_DEVICE);
475 }
476 }
477 };
478
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800479 private boolean isEnabled() {
480 if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
481 return false;
482 }
483
484 private boolean isValidDevice(BluetoothDevice device) {
485 if (device == null) return false;
486
487 if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
488 return false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700489 }
490
Priti Aghera349e62f2012-04-09 12:13:17 -0700491
492 /**
493 * Initiate virtual unplug for a HID input device.
494 *
495 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
496 *
497 * @param device Remote Bluetooth Device
498 * @return false on immediate error,
499 * true otherwise
500 * @hide
501 */
502 public boolean virtualUnplug(BluetoothDevice device) {
503 if (DBG) log("virtualUnplug(" + device + ")");
504 if (mService != null && isEnabled() && isValidDevice(device)) {
505 try {
506 return mService.virtualUnplug(device);
507 } catch (RemoteException e) {
508 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
509 return false;
510 }
511 }
512
513 if (mService == null) Log.w(TAG, "Proxy not attached to service");
514 return false;
515
516 }
517
518 /**
519 * Send Get_Protocol_Mode command to the connected HID input device.
520 *
521 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
522 *
523 * @param device Remote Bluetooth Device
524 * @return false on immediate error,
525 *true otherwise
526 * @hide
527 */
528 public boolean getProtocolMode(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700529 if (VDBG) log("getProtocolMode(" + device + ")");
Priti Aghera349e62f2012-04-09 12:13:17 -0700530 if (mService != null && isEnabled() && isValidDevice(device)) {
531 try {
532 return mService.getProtocolMode(device);
533 } catch (RemoteException e) {
534 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
535 return false;
536 }
537 }
538 if (mService == null) Log.w(TAG, "Proxy not attached to service");
539 return false;
540 }
541
542 /**
543 * Send Set_Protocol_Mode command to the connected HID input device.
544 *
545 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
546 *
547 * @param device Remote Bluetooth Device
548 * @return false on immediate error,
549 * true otherwise
550 * @hide
551 */
552 public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
553 if (DBG) log("setProtocolMode(" + device + ")");
554 if (mService != null && isEnabled() && isValidDevice(device)) {
555 try {
556 return mService.setProtocolMode(device, protocolMode);
557 } catch (RemoteException e) {
558 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
559 return false;
560 }
561 }
562 if (mService == null) Log.w(TAG, "Proxy not attached to service");
563 return false;
564 }
565
566 /**
567 * Send Get_Report command to the connected HID input device.
568 *
569 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
570 *
571 * @param device Remote Bluetooth Device
572 * @param reportType Report type
573 * @param reportId Report ID
574 * @param bufferSize Report receiving buffer size
575 * @return false on immediate error,
576 * true otherwise
577 * @hide
578 */
579 public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) {
Matthew Xie563e4142012-10-09 22:10:37 -0700580 if (VDBG) log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId + "bufferSize=" + bufferSize);
Priti Aghera349e62f2012-04-09 12:13:17 -0700581 if (mService != null && isEnabled() && isValidDevice(device)) {
582 try {
583 return mService.getReport(device, reportType, reportId, bufferSize);
584 } catch (RemoteException e) {
585 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
586 return false;
587 }
588 }
589 if (mService == null) Log.w(TAG, "Proxy not attached to service");
590 return false;
591 }
592
593 /**
594 * Send Set_Report command to the connected HID input device.
595 *
596 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
597 *
598 * @param device Remote Bluetooth Device
599 * @param reportType Report type
600 * @param report Report receiving buffer size
601 * @return false on immediate error,
602 * true otherwise
603 * @hide
604 */
605 public boolean setReport(BluetoothDevice device, byte reportType, String report) {
606 if (DBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
607 if (mService != null && isEnabled() && isValidDevice(device)) {
608 try {
609 return mService.setReport(device, reportType, report);
610 } catch (RemoteException e) {
611 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
612 return false;
613 }
614 }
615 if (mService == null) Log.w(TAG, "Proxy not attached to service");
616 return false;
617 }
618
619 /**
620 * Send Send_Data command to the connected HID input device.
621 *
622 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
623 *
624 * @param device Remote Bluetooth Device
625 * @param data Data to send
626 * @return false on immediate error,
627 * true otherwise
628 * @hide
629 */
630 public boolean sendData(BluetoothDevice device, String report) {
631 if (DBG) log("sendData(" + device + "), report=" + report);
632 if (mService != null && isEnabled() && isValidDevice(device)) {
633 try {
634 return mService.sendData(device, report);
635 } catch (RemoteException e) {
636 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
637 return false;
638 }
639 }
640 if (mService == null) Log.w(TAG, "Proxy not attached to service");
641 return false;
642 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700643 private static void log(String msg) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800644 Log.d(TAG, msg);
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700645 }
646}