blob: bff966d4d267993d67bcf4cac5c3c85668506fed [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;
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
78
79 /**
80 * @hide
81 */
82 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
83 public static final String ACTION_VIRTUAL_UNPLUG_STATUS =
84 "android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS";
85
86
87 /**
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -080088 * Return codes for the connect and disconnect Bluez / Dbus calls.
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080089 * @hide
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -080090 */
91 public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000;
92
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080093 /**
94 * @hide
95 */
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -080096 public static final int INPUT_CONNECT_FAILED_ALREADY_CONNECTED = 5001;
97
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080098 /**
99 * @hide
100 */
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -0800101 public static final int INPUT_CONNECT_FAILED_ATTEMPT_FAILED = 5002;
102
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800103 /**
104 * @hide
105 */
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -0800106 public static final int INPUT_OPERATION_GENERIC_FAILURE = 5003;
107
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800108 /**
109 * @hide
110 */
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -0800111 public static final int INPUT_OPERATION_SUCCESS = 5004;
112
Priti Aghera349e62f2012-04-09 12:13:17 -0700113 /**
114 * @hide
115 */
116 public static final int PROTOCOL_REPORT_MODE = 0;
117
118 /**
119 * @hide
120 */
121 public static final int PROTOCOL_BOOT_MODE = 1;
122
123 /**
124 * @hide
125 */
126 public static final int PROTOCOL_UNSUPPORTED_MODE = 255;
127
128 /* int reportType, int reportType, int bufferSize */
129 /**
130 * @hide
131 */
132 public static final byte REPORT_TYPE_INPUT = 0;
133
134 /**
135 * @hide
136 */
137 public static final byte REPORT_TYPE_OUTPUT = 1;
138
139 /**
140 * @hide
141 */
142 public static final byte REPORT_TYPE_FEATURE = 2;
143
144 /**
145 * @hide
146 */
147 public static final int VIRTUAL_UNPLUG_STATUS_SUCCESS = 0;
148
149 /**
150 * @hide
151 */
152 public static final int VIRTUAL_UNPLUG_STATUS_FAIL = 1;
153
154 /**
155 * @hide
156 */
157 public static final String EXTRA_PROTOCOL_MODE = "android.bluetooth.BluetoothInputDevice.extra.PROTOCOL_MODE";
158
159 /**
160 * @hide
161 */
162 public static final String EXTRA_REPORT_TYPE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_TYPE";
163
164 /**
165 * @hide
166 */
167 public static final String EXTRA_REPORT_ID = "android.bluetooth.BluetoothInputDevice.extra.REPORT_ID";
168
169 /**
170 * @hide
171 */
172 public static final String EXTRA_REPORT_BUFFER_SIZE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_BUFFER_SIZE";
173
174 /**
175 * @hide
176 */
177 public static final String EXTRA_REPORT = "android.bluetooth.BluetoothInputDevice.extra.REPORT";
178
179 /**
180 * @hide
181 */
182 public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS";
183
Matthew Xiebf246ef2012-03-21 23:15:06 -0700184 private Context mContext;
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800185 private ServiceListener mServiceListener;
186 private BluetoothAdapter mAdapter;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700187 private IBluetoothInputDevice mService;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700188
fredc0f420372012-04-12 00:02:00 -0700189 final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
190 new IBluetoothStateChangeCallback.Stub() {
191 public void onBluetoothStateChange(boolean up) {
192 if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
193 if (!up) {
194 if (DBG) Log.d(TAG,"Unbinding service...");
195 synchronized (mConnection) {
196 try {
197 mService = null;
198 mContext.unbindService(mConnection);
199 } catch (Exception re) {
200 Log.e(TAG,"",re);
201 }
202 }
203 } else {
204 synchronized (mConnection) {
205 try {
206 if (mService == null) {
207 if (DBG) Log.d(TAG,"Binding service...");
208 if (!mContext.bindService(new Intent(IBluetoothInputDevice.class.getName()), mConnection, 0)) {
209 Log.e(TAG, "Could not bind to Bluetooth HID Service");
210 }
211 }
212 } catch (Exception re) {
213 Log.e(TAG,"",re);
214 }
215 }
216 }
217 }
218 };
219
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700220 /**
221 * Create a BluetoothInputDevice proxy object for interacting with the local
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800222 * Bluetooth Service which handles the InputDevice profile
223 *
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700224 */
Matthew Xiebf246ef2012-03-21 23:15:06 -0700225 /*package*/ BluetoothInputDevice(Context context, ServiceListener l) {
226 mContext = context;
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800227 mServiceListener = l;
228 mAdapter = BluetoothAdapter.getDefaultAdapter();
fredc0f420372012-04-12 00:02:00 -0700229
230 IBluetoothManager mgr = mAdapter.getBluetoothManager();
231 if (mgr != null) {
232 try {
233 mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
234 } catch (RemoteException e) {
235 Log.e(TAG,"",e);
236 }
237 }
238
Matthew Xiebf246ef2012-03-21 23:15:06 -0700239 if (!context.bindService(new Intent(IBluetoothInputDevice.class.getName()),
240 mConnection, 0)) {
241 Log.e(TAG, "Could not bind to Bluetooth HID Service");
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700242 }
243 }
244
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800245 /*package*/ void close() {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700246 if (DBG) log("close()");
fredc0f420372012-04-12 00:02:00 -0700247 IBluetoothManager mgr = mAdapter.getBluetoothManager();
248 if (mgr != null) {
249 try {
250 mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
251 } catch (Exception e) {
252 Log.e(TAG,"",e);
253 }
254 }
255
256 synchronized (mConnection) {
257 if (mService != null) {
258 try {
259 mService = null;
260 mContext.unbindService(mConnection);
261 } catch (Exception re) {
262 Log.e(TAG,"",re);
263 }
264 }
Matthew Xiebf246ef2012-03-21 23:15:06 -0700265 }
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800266 mServiceListener = null;
267 }
268
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800269 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700270 * Initiate connection to a profile of the remote bluetooth device.
271 *
272 * <p> The system supports connection to multiple input devices.
273 *
274 * <p> This API returns false in scenarios like the profile on the
275 * device is already connected or Bluetooth is not turned on.
276 * When this API returns true, it is guaranteed that
277 * connection state intent for the profile will be broadcasted with
278 * the state. Users can get the connection state of the profile
279 * from this intent.
280 *
281 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
282 * permission.
283 *
284 * @param device Remote Bluetooth Device
285 * @return false on immediate error,
286 * true otherwise
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800287 * @hide
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700288 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800289 public boolean connect(BluetoothDevice device) {
290 if (DBG) log("connect(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700291 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800292 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700293 return mService.connect(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800294 } catch (RemoteException e) {
295 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
296 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700297 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700298 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800299 if (mService == null) Log.w(TAG, "Proxy not attached to service");
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700300 return false;
301 }
302
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800303 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700304 * Initiate disconnection from a profile
305 *
306 * <p> This API will return false in scenarios like the profile on the
307 * Bluetooth device is not in connected state etc. When this API returns,
308 * true, it is guaranteed that the connection state change
309 * intent will be broadcasted with the state. Users can get the
310 * disconnection state of the profile from this intent.
311 *
312 * <p> If the disconnection is initiated by a remote device, the state
313 * will transition from {@link #STATE_CONNECTED} to
314 * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
315 * host (local) device the state will transition from
316 * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
317 * state {@link #STATE_DISCONNECTED}. The transition to
318 * {@link #STATE_DISCONNECTING} can be used to distinguish between the
319 * two scenarios.
320 *
321 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
322 * permission.
323 *
324 * @param device Remote Bluetooth Device
325 * @return false on immediate error,
326 * true otherwise
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700327 * @hide
328 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800329 public boolean disconnect(BluetoothDevice device) {
330 if (DBG) log("disconnect(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700331 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800332 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700333 return mService.disconnect(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800334 } catch (RemoteException e) {
335 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
336 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700337 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700338 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800339 if (mService == null) Log.w(TAG, "Proxy not attached to service");
340 return false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700341 }
342
343 /**
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800344 * {@inheritDoc}
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700345 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800346 public List<BluetoothDevice> getConnectedDevices() {
347 if (DBG) log("getConnectedDevices()");
348 if (mService != null && isEnabled()) {
349 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700350 return mService.getConnectedDevices();
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800351 } catch (RemoteException e) {
352 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
353 return new ArrayList<BluetoothDevice>();
Matthew Xiebf246ef2012-03-21 23:15:06 -0700354 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700355 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800356 if (mService == null) Log.w(TAG, "Proxy not attached to service");
357 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700358 }
359
360 /**
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800361 * {@inheritDoc}
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700362 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800363 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
364 if (DBG) log("getDevicesMatchingStates()");
365 if (mService != null && isEnabled()) {
366 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700367 return mService.getDevicesMatchingConnectionStates(states);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800368 } catch (RemoteException e) {
369 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
370 return new ArrayList<BluetoothDevice>();
Matthew Xiebf246ef2012-03-21 23:15:06 -0700371 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700372 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800373 if (mService == null) Log.w(TAG, "Proxy not attached to service");
374 return new ArrayList<BluetoothDevice>();
375 }
376
377 /**
378 * {@inheritDoc}
379 */
380 public int getConnectionState(BluetoothDevice device) {
381 if (DBG) log("getState(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700382 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800383 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700384 return mService.getConnectionState(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800385 } catch (RemoteException e) {
386 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
387 return BluetoothProfile.STATE_DISCONNECTED;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700388 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800389 }
390 if (mService == null) Log.w(TAG, "Proxy not attached to service");
391 return BluetoothProfile.STATE_DISCONNECTED;
392 }
393
394 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700395 * Set priority of the profile
396 *
397 * <p> The device should already be paired.
398 * Priority can be one of {@link #PRIORITY_ON} or
399 * {@link #PRIORITY_OFF},
400 *
401 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
402 * permission.
403 *
404 * @param device Paired bluetooth device
405 * @param priority
406 * @return true if priority is set, false on error
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800407 * @hide
408 */
409 public boolean setPriority(BluetoothDevice device, int priority) {
410 if (DBG) log("setPriority(" + device + ", " + priority + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700411 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800412 if (priority != BluetoothProfile.PRIORITY_OFF &&
413 priority != BluetoothProfile.PRIORITY_ON) {
414 return false;
415 }
416 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700417 return mService.setPriority(device, priority);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800418 } catch (RemoteException e) {
419 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
420 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700421 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800422 }
423 if (mService == null) Log.w(TAG, "Proxy not attached to service");
424 return false;
425 }
426
427 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700428 * Get the priority of the profile.
429 *
430 * <p> The priority can be any of:
431 * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
432 * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
433 *
434 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
435 *
436 * @param device Bluetooth device
437 * @return priority of the device
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800438 * @hide
439 */
440 public int getPriority(BluetoothDevice device) {
441 if (DBG) log("getPriority(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700442 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800443 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700444 return mService.getPriority(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800445 } catch (RemoteException e) {
446 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
447 return BluetoothProfile.PRIORITY_OFF;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700448 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800449 }
450 if (mService == null) Log.w(TAG, "Proxy not attached to service");
451 return BluetoothProfile.PRIORITY_OFF;
452 }
453
Matthew Xiebf246ef2012-03-21 23:15:06 -0700454 private ServiceConnection mConnection = new ServiceConnection() {
455 public void onServiceConnected(ComponentName className, IBinder service) {
456 if (DBG) Log.d(TAG, "Proxy object connected");
457 mService = IBluetoothInputDevice.Stub.asInterface(service);
458
459 if (mServiceListener != null) {
460 mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, BluetoothInputDevice.this);
461 }
462 }
463 public void onServiceDisconnected(ComponentName className) {
464 if (DBG) Log.d(TAG, "Proxy object disconnected");
465 mService = null;
466 if (mServiceListener != null) {
467 mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_DEVICE);
468 }
469 }
470 };
471
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800472 private boolean isEnabled() {
473 if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
474 return false;
475 }
476
477 private boolean isValidDevice(BluetoothDevice device) {
478 if (device == null) return false;
479
480 if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
481 return false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700482 }
483
Priti Aghera349e62f2012-04-09 12:13:17 -0700484
485 /**
486 * Initiate virtual unplug for a HID input device.
487 *
488 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
489 *
490 * @param device Remote Bluetooth Device
491 * @return false on immediate error,
492 * true otherwise
493 * @hide
494 */
495 public boolean virtualUnplug(BluetoothDevice device) {
496 if (DBG) log("virtualUnplug(" + device + ")");
497 if (mService != null && isEnabled() && isValidDevice(device)) {
498 try {
499 return mService.virtualUnplug(device);
500 } catch (RemoteException e) {
501 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
502 return false;
503 }
504 }
505
506 if (mService == null) Log.w(TAG, "Proxy not attached to service");
507 return false;
508
509 }
510
511 /**
512 * Send Get_Protocol_Mode command to the connected HID input device.
513 *
514 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
515 *
516 * @param device Remote Bluetooth Device
517 * @return false on immediate error,
518 *true otherwise
519 * @hide
520 */
521 public boolean getProtocolMode(BluetoothDevice device) {
522 if (DBG) log("getProtocolMode(" + device + ")");
523 if (mService != null && isEnabled() && isValidDevice(device)) {
524 try {
525 return mService.getProtocolMode(device);
526 } catch (RemoteException e) {
527 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
528 return false;
529 }
530 }
531 if (mService == null) Log.w(TAG, "Proxy not attached to service");
532 return false;
533 }
534
535 /**
536 * Send Set_Protocol_Mode command to the connected HID input device.
537 *
538 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
539 *
540 * @param device Remote Bluetooth Device
541 * @return false on immediate error,
542 * true otherwise
543 * @hide
544 */
545 public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
546 if (DBG) log("setProtocolMode(" + device + ")");
547 if (mService != null && isEnabled() && isValidDevice(device)) {
548 try {
549 return mService.setProtocolMode(device, protocolMode);
550 } catch (RemoteException e) {
551 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
552 return false;
553 }
554 }
555 if (mService == null) Log.w(TAG, "Proxy not attached to service");
556 return false;
557 }
558
559 /**
560 * Send Get_Report command to the connected HID input device.
561 *
562 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
563 *
564 * @param device Remote Bluetooth Device
565 * @param reportType Report type
566 * @param reportId Report ID
567 * @param bufferSize Report receiving buffer size
568 * @return false on immediate error,
569 * true otherwise
570 * @hide
571 */
572 public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) {
573 if (DBG) log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId + "bufferSize=" + bufferSize);
574 if (mService != null && isEnabled() && isValidDevice(device)) {
575 try {
576 return mService.getReport(device, reportType, reportId, bufferSize);
577 } catch (RemoteException e) {
578 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
579 return false;
580 }
581 }
582 if (mService == null) Log.w(TAG, "Proxy not attached to service");
583 return false;
584 }
585
586 /**
587 * Send Set_Report command to the connected HID input device.
588 *
589 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
590 *
591 * @param device Remote Bluetooth Device
592 * @param reportType Report type
593 * @param report Report receiving buffer size
594 * @return false on immediate error,
595 * true otherwise
596 * @hide
597 */
598 public boolean setReport(BluetoothDevice device, byte reportType, String report) {
599 if (DBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
600 if (mService != null && isEnabled() && isValidDevice(device)) {
601 try {
602 return mService.setReport(device, reportType, report);
603 } catch (RemoteException e) {
604 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
605 return false;
606 }
607 }
608 if (mService == null) Log.w(TAG, "Proxy not attached to service");
609 return false;
610 }
611
612 /**
613 * Send Send_Data command to the connected HID input device.
614 *
615 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
616 *
617 * @param device Remote Bluetooth Device
618 * @param data Data to send
619 * @return false on immediate error,
620 * true otherwise
621 * @hide
622 */
623 public boolean sendData(BluetoothDevice device, String report) {
624 if (DBG) log("sendData(" + device + "), report=" + report);
625 if (mService != null && isEnabled() && isValidDevice(device)) {
626 try {
627 return mService.sendData(device, report);
628 } catch (RemoteException e) {
629 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
630 return false;
631 }
632 }
633 if (mService == null) Log.w(TAG, "Proxy not attached to service");
634 return false;
635 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700636 private static void log(String msg) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800637 Log.d(TAG, msg);
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700638 }
639}