blob: db7e424d40ee2837893838d995eb0da9616c0bd8 [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 */
133 public static final byte REPORT_TYPE_INPUT = 0;
134
135 /**
136 * @hide
137 */
138 public static final byte REPORT_TYPE_OUTPUT = 1;
139
140 /**
141 * @hide
142 */
143 public static final byte REPORT_TYPE_FEATURE = 2;
144
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...");
fredc0f420372012-04-12 00:02:00 -0700209 if (!mContext.bindService(new Intent(IBluetoothInputDevice.class.getName()), mConnection, 0)) {
210 Log.e(TAG, "Could not bind to Bluetooth HID Service");
211 }
212 }
213 } catch (Exception re) {
214 Log.e(TAG,"",re);
215 }
216 }
217 }
218 }
219 };
220
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700221 /**
222 * Create a BluetoothInputDevice proxy object for interacting with the local
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800223 * Bluetooth Service which handles the InputDevice profile
224 *
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700225 */
Matthew Xiebf246ef2012-03-21 23:15:06 -0700226 /*package*/ BluetoothInputDevice(Context context, ServiceListener l) {
227 mContext = context;
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800228 mServiceListener = l;
229 mAdapter = BluetoothAdapter.getDefaultAdapter();
fredc0f420372012-04-12 00:02:00 -0700230
231 IBluetoothManager mgr = mAdapter.getBluetoothManager();
232 if (mgr != null) {
233 try {
234 mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
235 } catch (RemoteException e) {
236 Log.e(TAG,"",e);
237 }
238 }
239
Matthew Xiebf246ef2012-03-21 23:15:06 -0700240 if (!context.bindService(new Intent(IBluetoothInputDevice.class.getName()),
241 mConnection, 0)) {
242 Log.e(TAG, "Could not bind to Bluetooth HID Service");
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700243 }
244 }
245
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800246 /*package*/ void close() {
Matthew Xie563e4142012-10-09 22:10:37 -0700247 if (VDBG) log("close()");
fredc0f420372012-04-12 00:02:00 -0700248 IBluetoothManager mgr = mAdapter.getBluetoothManager();
249 if (mgr != null) {
250 try {
251 mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
252 } catch (Exception e) {
253 Log.e(TAG,"",e);
254 }
255 }
256
257 synchronized (mConnection) {
258 if (mService != null) {
259 try {
260 mService = null;
261 mContext.unbindService(mConnection);
262 } catch (Exception re) {
263 Log.e(TAG,"",re);
264 }
265 }
Matthew Xiebf246ef2012-03-21 23:15:06 -0700266 }
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800267 mServiceListener = null;
268 }
269
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800270 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700271 * Initiate connection to a profile of the remote bluetooth device.
272 *
273 * <p> The system supports connection to multiple input devices.
274 *
275 * <p> This API returns false in scenarios like the profile on the
276 * device is already connected or Bluetooth is not turned on.
277 * When this API returns true, it is guaranteed that
278 * connection state intent for the profile will be broadcasted with
279 * the state. Users can get the connection state of the profile
280 * from this intent.
281 *
282 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
283 * permission.
284 *
285 * @param device Remote Bluetooth Device
286 * @return false on immediate error,
287 * true otherwise
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800288 * @hide
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700289 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800290 public boolean connect(BluetoothDevice device) {
291 if (DBG) log("connect(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700292 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800293 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700294 return mService.connect(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800295 } catch (RemoteException e) {
296 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
297 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700298 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700299 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800300 if (mService == null) Log.w(TAG, "Proxy not attached to service");
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700301 return false;
302 }
303
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800304 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700305 * Initiate disconnection from a profile
306 *
307 * <p> This API will return false in scenarios like the profile on the
308 * Bluetooth device is not in connected state etc. When this API returns,
309 * true, it is guaranteed that the connection state change
310 * intent will be broadcasted with the state. Users can get the
311 * disconnection state of the profile from this intent.
312 *
313 * <p> If the disconnection is initiated by a remote device, the state
314 * will transition from {@link #STATE_CONNECTED} to
315 * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
316 * host (local) device the state will transition from
317 * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
318 * state {@link #STATE_DISCONNECTED}. The transition to
319 * {@link #STATE_DISCONNECTING} can be used to distinguish between the
320 * two scenarios.
321 *
322 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
323 * permission.
324 *
325 * @param device Remote Bluetooth Device
326 * @return false on immediate error,
327 * true otherwise
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700328 * @hide
329 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800330 public boolean disconnect(BluetoothDevice device) {
331 if (DBG) log("disconnect(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700332 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800333 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700334 return mService.disconnect(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800335 } catch (RemoteException e) {
336 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
337 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700338 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700339 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800340 if (mService == null) Log.w(TAG, "Proxy not attached to service");
341 return false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700342 }
343
344 /**
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800345 * {@inheritDoc}
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700346 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800347 public List<BluetoothDevice> getConnectedDevices() {
Matthew Xie563e4142012-10-09 22:10:37 -0700348 if (VDBG) log("getConnectedDevices()");
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800349 if (mService != null && isEnabled()) {
350 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700351 return mService.getConnectedDevices();
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800352 } catch (RemoteException e) {
353 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
354 return new ArrayList<BluetoothDevice>();
Matthew Xiebf246ef2012-03-21 23:15:06 -0700355 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700356 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800357 if (mService == null) Log.w(TAG, "Proxy not attached to service");
358 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700359 }
360
361 /**
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800362 * {@inheritDoc}
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700363 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800364 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Matthew Xie563e4142012-10-09 22:10:37 -0700365 if (VDBG) log("getDevicesMatchingStates()");
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800366 if (mService != null && isEnabled()) {
367 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700368 return mService.getDevicesMatchingConnectionStates(states);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800369 } catch (RemoteException e) {
370 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
371 return new ArrayList<BluetoothDevice>();
Matthew Xiebf246ef2012-03-21 23:15:06 -0700372 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700373 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800374 if (mService == null) Log.w(TAG, "Proxy not attached to service");
375 return new ArrayList<BluetoothDevice>();
376 }
377
378 /**
379 * {@inheritDoc}
380 */
381 public int getConnectionState(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700382 if (VDBG) log("getState(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700383 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800384 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700385 return mService.getConnectionState(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800386 } catch (RemoteException e) {
387 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
388 return BluetoothProfile.STATE_DISCONNECTED;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700389 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800390 }
391 if (mService == null) Log.w(TAG, "Proxy not attached to service");
392 return BluetoothProfile.STATE_DISCONNECTED;
393 }
394
395 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700396 * Set priority of the profile
397 *
398 * <p> The device should already be paired.
399 * Priority can be one of {@link #PRIORITY_ON} or
400 * {@link #PRIORITY_OFF},
401 *
402 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
403 * permission.
404 *
405 * @param device Paired bluetooth device
406 * @param priority
407 * @return true if priority is set, false on error
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800408 * @hide
409 */
410 public boolean setPriority(BluetoothDevice device, int priority) {
411 if (DBG) log("setPriority(" + device + ", " + priority + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700412 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800413 if (priority != BluetoothProfile.PRIORITY_OFF &&
414 priority != BluetoothProfile.PRIORITY_ON) {
415 return false;
416 }
417 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700418 return mService.setPriority(device, priority);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800419 } catch (RemoteException e) {
420 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
421 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700422 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800423 }
424 if (mService == null) Log.w(TAG, "Proxy not attached to service");
425 return false;
426 }
427
428 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700429 * Get the priority of the profile.
430 *
431 * <p> The priority can be any of:
432 * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
433 * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
434 *
435 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
436 *
437 * @param device Bluetooth device
438 * @return priority of the device
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800439 * @hide
440 */
441 public int getPriority(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700442 if (VDBG) log("getPriority(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700443 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800444 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700445 return mService.getPriority(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800446 } catch (RemoteException e) {
447 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
448 return BluetoothProfile.PRIORITY_OFF;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700449 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800450 }
451 if (mService == null) Log.w(TAG, "Proxy not attached to service");
452 return BluetoothProfile.PRIORITY_OFF;
453 }
454
Matthew Xiebf246ef2012-03-21 23:15:06 -0700455 private ServiceConnection mConnection = new ServiceConnection() {
456 public void onServiceConnected(ComponentName className, IBinder service) {
457 if (DBG) Log.d(TAG, "Proxy object connected");
458 mService = IBluetoothInputDevice.Stub.asInterface(service);
459
460 if (mServiceListener != null) {
461 mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, BluetoothInputDevice.this);
462 }
463 }
464 public void onServiceDisconnected(ComponentName className) {
465 if (DBG) Log.d(TAG, "Proxy object disconnected");
466 mService = null;
467 if (mServiceListener != null) {
468 mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_DEVICE);
469 }
470 }
471 };
472
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800473 private boolean isEnabled() {
474 if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
475 return false;
476 }
477
478 private boolean isValidDevice(BluetoothDevice device) {
479 if (device == null) return false;
480
481 if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
482 return false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700483 }
484
Priti Aghera349e62f2012-04-09 12:13:17 -0700485
486 /**
487 * Initiate virtual unplug for a HID input device.
488 *
489 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
490 *
491 * @param device Remote Bluetooth Device
492 * @return false on immediate error,
493 * true otherwise
494 * @hide
495 */
496 public boolean virtualUnplug(BluetoothDevice device) {
497 if (DBG) log("virtualUnplug(" + device + ")");
498 if (mService != null && isEnabled() && isValidDevice(device)) {
499 try {
500 return mService.virtualUnplug(device);
501 } catch (RemoteException e) {
502 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
503 return false;
504 }
505 }
506
507 if (mService == null) Log.w(TAG, "Proxy not attached to service");
508 return false;
509
510 }
511
512 /**
513 * Send Get_Protocol_Mode command to the connected HID input device.
514 *
515 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
516 *
517 * @param device Remote Bluetooth Device
518 * @return false on immediate error,
519 *true otherwise
520 * @hide
521 */
522 public boolean getProtocolMode(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700523 if (VDBG) log("getProtocolMode(" + device + ")");
Priti Aghera349e62f2012-04-09 12:13:17 -0700524 if (mService != null && isEnabled() && isValidDevice(device)) {
525 try {
526 return mService.getProtocolMode(device);
527 } catch (RemoteException e) {
528 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
529 return false;
530 }
531 }
532 if (mService == null) Log.w(TAG, "Proxy not attached to service");
533 return false;
534 }
535
536 /**
537 * Send Set_Protocol_Mode command to the connected HID input device.
538 *
539 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
540 *
541 * @param device Remote Bluetooth Device
542 * @return false on immediate error,
543 * true otherwise
544 * @hide
545 */
546 public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
547 if (DBG) log("setProtocolMode(" + device + ")");
548 if (mService != null && isEnabled() && isValidDevice(device)) {
549 try {
550 return mService.setProtocolMode(device, protocolMode);
551 } catch (RemoteException e) {
552 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
553 return false;
554 }
555 }
556 if (mService == null) Log.w(TAG, "Proxy not attached to service");
557 return false;
558 }
559
560 /**
561 * Send Get_Report command to the connected HID input device.
562 *
563 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
564 *
565 * @param device Remote Bluetooth Device
566 * @param reportType Report type
567 * @param reportId Report ID
568 * @param bufferSize Report receiving buffer size
569 * @return false on immediate error,
570 * true otherwise
571 * @hide
572 */
573 public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) {
Matthew Xie563e4142012-10-09 22:10:37 -0700574 if (VDBG) log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId + "bufferSize=" + bufferSize);
Priti Aghera349e62f2012-04-09 12:13:17 -0700575 if (mService != null && isEnabled() && isValidDevice(device)) {
576 try {
577 return mService.getReport(device, reportType, reportId, bufferSize);
578 } catch (RemoteException e) {
579 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
580 return false;
581 }
582 }
583 if (mService == null) Log.w(TAG, "Proxy not attached to service");
584 return false;
585 }
586
587 /**
588 * Send Set_Report command to the connected HID input device.
589 *
590 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
591 *
592 * @param device Remote Bluetooth Device
593 * @param reportType Report type
594 * @param report Report receiving buffer size
595 * @return false on immediate error,
596 * true otherwise
597 * @hide
598 */
599 public boolean setReport(BluetoothDevice device, byte reportType, String report) {
600 if (DBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
601 if (mService != null && isEnabled() && isValidDevice(device)) {
602 try {
603 return mService.setReport(device, reportType, report);
604 } catch (RemoteException e) {
605 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
606 return false;
607 }
608 }
609 if (mService == null) Log.w(TAG, "Proxy not attached to service");
610 return false;
611 }
612
613 /**
614 * Send Send_Data command to the connected HID input device.
615 *
616 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
617 *
618 * @param device Remote Bluetooth Device
619 * @param data Data to send
620 * @return false on immediate error,
621 * true otherwise
622 * @hide
623 */
624 public boolean sendData(BluetoothDevice device, String report) {
625 if (DBG) log("sendData(" + device + "), report=" + report);
626 if (mService != null && isEnabled() && isValidDevice(device)) {
627 try {
628 return mService.sendData(device, report);
629 } catch (RemoteException e) {
630 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
631 return false;
632 }
633 }
634 if (mService == null) Log.w(TAG, "Proxy not attached to service");
635 return false;
636 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700637 private static void log(String msg) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800638 Log.d(TAG, msg);
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700639 }
640}