blob: 33232edf58cc83f0567313944438f1b03653d4ab [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
Mike J. Chend96d5cf2014-01-27 17:55:40 -080079 /**
80 * @hide
81 */
82 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
83 public static final String ACTION_REPORT =
84 "android.bluetooth.input.profile.action.REPORT";
Priti Aghera349e62f2012-04-09 12:13:17 -070085
86 /**
87 * @hide
88 */
89 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
90 public static final String ACTION_VIRTUAL_UNPLUG_STATUS =
91 "android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS";
92
93
94 /**
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -080095 * Return codes for the connect and disconnect Bluez / Dbus calls.
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -080096 * @hide
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -080097 */
98 public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000;
99
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800100 /**
101 * @hide
102 */
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -0800103 public static final int INPUT_CONNECT_FAILED_ALREADY_CONNECTED = 5001;
104
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800105 /**
106 * @hide
107 */
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -0800108 public static final int INPUT_CONNECT_FAILED_ATTEMPT_FAILED = 5002;
109
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800110 /**
111 * @hide
112 */
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -0800113 public static final int INPUT_OPERATION_GENERIC_FAILURE = 5003;
114
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800115 /**
116 * @hide
117 */
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -0800118 public static final int INPUT_OPERATION_SUCCESS = 5004;
119
Priti Aghera349e62f2012-04-09 12:13:17 -0700120 /**
121 * @hide
122 */
123 public static final int PROTOCOL_REPORT_MODE = 0;
124
125 /**
126 * @hide
127 */
128 public static final int PROTOCOL_BOOT_MODE = 1;
129
130 /**
131 * @hide
132 */
133 public static final int PROTOCOL_UNSUPPORTED_MODE = 255;
134
135 /* int reportType, int reportType, int bufferSize */
136 /**
137 * @hide
138 */
Mike J. Chen1b47f7c2014-01-27 16:27:04 -0800139 public static final byte REPORT_TYPE_INPUT = 1;
Priti Aghera349e62f2012-04-09 12:13:17 -0700140
141 /**
142 * @hide
143 */
Mike J. Chen1b47f7c2014-01-27 16:27:04 -0800144 public static final byte REPORT_TYPE_OUTPUT = 2;
Priti Aghera349e62f2012-04-09 12:13:17 -0700145
146 /**
147 * @hide
148 */
Mike J. Chen1b47f7c2014-01-27 16:27:04 -0800149 public static final byte REPORT_TYPE_FEATURE = 3;
Priti Aghera349e62f2012-04-09 12:13:17 -0700150
151 /**
152 * @hide
153 */
154 public static final int VIRTUAL_UNPLUG_STATUS_SUCCESS = 0;
155
156 /**
157 * @hide
158 */
159 public static final int VIRTUAL_UNPLUG_STATUS_FAIL = 1;
160
161 /**
162 * @hide
163 */
164 public static final String EXTRA_PROTOCOL_MODE = "android.bluetooth.BluetoothInputDevice.extra.PROTOCOL_MODE";
165
166 /**
167 * @hide
168 */
169 public static final String EXTRA_REPORT_TYPE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_TYPE";
170
171 /**
172 * @hide
173 */
174 public static final String EXTRA_REPORT_ID = "android.bluetooth.BluetoothInputDevice.extra.REPORT_ID";
175
176 /**
177 * @hide
178 */
179 public static final String EXTRA_REPORT_BUFFER_SIZE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_BUFFER_SIZE";
180
181 /**
182 * @hide
183 */
184 public static final String EXTRA_REPORT = "android.bluetooth.BluetoothInputDevice.extra.REPORT";
185
186 /**
187 * @hide
188 */
189 public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS";
190
Matthew Xiebf246ef2012-03-21 23:15:06 -0700191 private Context mContext;
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800192 private ServiceListener mServiceListener;
193 private BluetoothAdapter mAdapter;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700194 private IBluetoothInputDevice mService;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700195
fredc0f420372012-04-12 00:02:00 -0700196 final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
197 new IBluetoothStateChangeCallback.Stub() {
198 public void onBluetoothStateChange(boolean up) {
199 if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
200 if (!up) {
Matthew Xie563e4142012-10-09 22:10:37 -0700201 if (VDBG) Log.d(TAG,"Unbinding service...");
fredc0f420372012-04-12 00:02:00 -0700202 synchronized (mConnection) {
203 try {
204 mService = null;
205 mContext.unbindService(mConnection);
206 } catch (Exception re) {
207 Log.e(TAG,"",re);
208 }
209 }
210 } else {
211 synchronized (mConnection) {
212 try {
213 if (mService == null) {
Matthew Xie563e4142012-10-09 22:10:37 -0700214 if (VDBG) Log.d(TAG,"Binding service...");
Dianne Hackborn221ea892013-08-04 16:50:16 -0700215 doBind();
fredc0f420372012-04-12 00:02:00 -0700216 }
217 } catch (Exception re) {
218 Log.e(TAG,"",re);
219 }
220 }
221 }
222 }
223 };
224
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700225 /**
226 * Create a BluetoothInputDevice proxy object for interacting with the local
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800227 * Bluetooth Service which handles the InputDevice profile
228 *
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700229 */
Matthew Xiebf246ef2012-03-21 23:15:06 -0700230 /*package*/ BluetoothInputDevice(Context context, ServiceListener l) {
231 mContext = context;
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800232 mServiceListener = l;
233 mAdapter = BluetoothAdapter.getDefaultAdapter();
fredc0f420372012-04-12 00:02:00 -0700234
235 IBluetoothManager mgr = mAdapter.getBluetoothManager();
236 if (mgr != null) {
237 try {
238 mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
239 } catch (RemoteException e) {
240 Log.e(TAG,"",e);
241 }
242 }
243
Dianne Hackborn221ea892013-08-04 16:50:16 -0700244 doBind();
245 }
246
247 boolean doBind() {
248 Intent intent = new Intent(IBluetoothInputDevice.class.getName());
249 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
250 intent.setComponent(comp);
251 if (comp == null || !mContext.bindService(intent, mConnection, 0)) {
252 Log.e(TAG, "Could not bind to Bluetooth HID Service with " + intent);
253 return false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700254 }
Dianne Hackborn221ea892013-08-04 16:50:16 -0700255 return true;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700256 }
257
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800258 /*package*/ void close() {
Matthew Xie563e4142012-10-09 22:10:37 -0700259 if (VDBG) log("close()");
fredc0f420372012-04-12 00:02:00 -0700260 IBluetoothManager mgr = mAdapter.getBluetoothManager();
261 if (mgr != null) {
262 try {
263 mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
264 } catch (Exception e) {
265 Log.e(TAG,"",e);
266 }
267 }
268
269 synchronized (mConnection) {
270 if (mService != null) {
271 try {
272 mService = null;
273 mContext.unbindService(mConnection);
274 } catch (Exception re) {
275 Log.e(TAG,"",re);
276 }
277 }
Matthew Xiebf246ef2012-03-21 23:15:06 -0700278 }
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800279 mServiceListener = null;
280 }
281
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800282 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700283 * Initiate connection to a profile of the remote bluetooth device.
284 *
285 * <p> The system supports connection to multiple input devices.
286 *
287 * <p> This API returns false in scenarios like the profile on the
288 * device is already connected or Bluetooth is not turned on.
289 * When this API returns true, it is guaranteed that
290 * connection state intent for the profile will be broadcasted with
291 * the state. Users can get the connection state of the profile
292 * from this intent.
293 *
294 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
295 * permission.
296 *
297 * @param device Remote Bluetooth Device
298 * @return false on immediate error,
299 * true otherwise
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800300 * @hide
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700301 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800302 public boolean connect(BluetoothDevice device) {
303 if (DBG) log("connect(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700304 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800305 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700306 return mService.connect(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800307 } catch (RemoteException e) {
308 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
309 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700310 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700311 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800312 if (mService == null) Log.w(TAG, "Proxy not attached to service");
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700313 return false;
314 }
315
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800316 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700317 * Initiate disconnection from a profile
318 *
319 * <p> This API will return false in scenarios like the profile on the
320 * Bluetooth device is not in connected state etc. When this API returns,
321 * true, it is guaranteed that the connection state change
322 * intent will be broadcasted with the state. Users can get the
323 * disconnection state of the profile from this intent.
324 *
325 * <p> If the disconnection is initiated by a remote device, the state
326 * will transition from {@link #STATE_CONNECTED} to
327 * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
328 * host (local) device the state will transition from
329 * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
330 * state {@link #STATE_DISCONNECTED}. The transition to
331 * {@link #STATE_DISCONNECTING} can be used to distinguish between the
332 * two scenarios.
333 *
334 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
335 * permission.
336 *
337 * @param device Remote Bluetooth Device
338 * @return false on immediate error,
339 * true otherwise
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700340 * @hide
341 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800342 public boolean disconnect(BluetoothDevice device) {
343 if (DBG) log("disconnect(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700344 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800345 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700346 return mService.disconnect(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800347 } catch (RemoteException e) {
348 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
349 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700350 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700351 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800352 if (mService == null) Log.w(TAG, "Proxy not attached to service");
353 return false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700354 }
355
356 /**
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800357 * {@inheritDoc}
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700358 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800359 public List<BluetoothDevice> getConnectedDevices() {
Matthew Xie563e4142012-10-09 22:10:37 -0700360 if (VDBG) log("getConnectedDevices()");
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800361 if (mService != null && isEnabled()) {
362 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700363 return mService.getConnectedDevices();
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800364 } catch (RemoteException e) {
365 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
366 return new ArrayList<BluetoothDevice>();
Matthew Xiebf246ef2012-03-21 23:15:06 -0700367 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700368 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800369 if (mService == null) Log.w(TAG, "Proxy not attached to service");
370 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700371 }
372
373 /**
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800374 * {@inheritDoc}
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700375 */
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800376 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Matthew Xie563e4142012-10-09 22:10:37 -0700377 if (VDBG) log("getDevicesMatchingStates()");
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800378 if (mService != null && isEnabled()) {
379 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700380 return mService.getDevicesMatchingConnectionStates(states);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800381 } catch (RemoteException e) {
382 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
383 return new ArrayList<BluetoothDevice>();
Matthew Xiebf246ef2012-03-21 23:15:06 -0700384 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700385 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800386 if (mService == null) Log.w(TAG, "Proxy not attached to service");
387 return new ArrayList<BluetoothDevice>();
388 }
389
390 /**
391 * {@inheritDoc}
392 */
393 public int getConnectionState(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700394 if (VDBG) log("getState(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700395 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800396 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700397 return mService.getConnectionState(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800398 } catch (RemoteException e) {
399 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
400 return BluetoothProfile.STATE_DISCONNECTED;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700401 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800402 }
403 if (mService == null) Log.w(TAG, "Proxy not attached to service");
404 return BluetoothProfile.STATE_DISCONNECTED;
405 }
406
407 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700408 * Set priority of the profile
409 *
410 * <p> The device should already be paired.
411 * Priority can be one of {@link #PRIORITY_ON} or
412 * {@link #PRIORITY_OFF},
413 *
414 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
415 * permission.
416 *
417 * @param device Paired bluetooth device
418 * @param priority
419 * @return true if priority is set, false on error
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800420 * @hide
421 */
422 public boolean setPriority(BluetoothDevice device, int priority) {
423 if (DBG) log("setPriority(" + device + ", " + priority + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700424 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800425 if (priority != BluetoothProfile.PRIORITY_OFF &&
426 priority != BluetoothProfile.PRIORITY_ON) {
427 return false;
428 }
429 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700430 return mService.setPriority(device, priority);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800431 } catch (RemoteException e) {
432 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
433 return false;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700434 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800435 }
436 if (mService == null) Log.w(TAG, "Proxy not attached to service");
437 return false;
438 }
439
440 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700441 * Get the priority of the profile.
442 *
443 * <p> The priority can be any of:
444 * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
445 * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
446 *
447 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
448 *
449 * @param device Bluetooth device
450 * @return priority of the device
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800451 * @hide
452 */
453 public int getPriority(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700454 if (VDBG) log("getPriority(" + device + ")");
Matthew Xiebf246ef2012-03-21 23:15:06 -0700455 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800456 try {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700457 return mService.getPriority(device);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800458 } catch (RemoteException e) {
459 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
460 return BluetoothProfile.PRIORITY_OFF;
Matthew Xiebf246ef2012-03-21 23:15:06 -0700461 }
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800462 }
463 if (mService == null) Log.w(TAG, "Proxy not attached to service");
464 return BluetoothProfile.PRIORITY_OFF;
465 }
466
Matthew Xie9b693992013-10-10 11:21:40 -0700467 private final ServiceConnection mConnection = new ServiceConnection() {
Matthew Xiebf246ef2012-03-21 23:15:06 -0700468 public void onServiceConnected(ComponentName className, IBinder service) {
469 if (DBG) Log.d(TAG, "Proxy object connected");
470 mService = IBluetoothInputDevice.Stub.asInterface(service);
471
472 if (mServiceListener != null) {
473 mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, BluetoothInputDevice.this);
474 }
475 }
476 public void onServiceDisconnected(ComponentName className) {
477 if (DBG) Log.d(TAG, "Proxy object disconnected");
478 mService = null;
479 if (mServiceListener != null) {
480 mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_DEVICE);
481 }
482 }
483 };
484
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800485 private boolean isEnabled() {
486 if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
487 return false;
488 }
489
490 private boolean isValidDevice(BluetoothDevice device) {
491 if (device == null) return false;
492
493 if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
494 return false;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700495 }
496
Priti Aghera349e62f2012-04-09 12:13:17 -0700497
498 /**
499 * Initiate virtual unplug for a HID input device.
500 *
501 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
502 *
503 * @param device Remote Bluetooth Device
504 * @return false on immediate error,
505 * true otherwise
506 * @hide
507 */
508 public boolean virtualUnplug(BluetoothDevice device) {
509 if (DBG) log("virtualUnplug(" + device + ")");
510 if (mService != null && isEnabled() && isValidDevice(device)) {
511 try {
512 return mService.virtualUnplug(device);
513 } catch (RemoteException e) {
514 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
515 return false;
516 }
517 }
518
519 if (mService == null) Log.w(TAG, "Proxy not attached to service");
520 return false;
521
522 }
523
524 /**
525 * Send Get_Protocol_Mode command to the connected HID input device.
526 *
527 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
528 *
529 * @param device Remote Bluetooth Device
530 * @return false on immediate error,
531 *true otherwise
532 * @hide
533 */
534 public boolean getProtocolMode(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700535 if (VDBG) log("getProtocolMode(" + device + ")");
Priti Aghera349e62f2012-04-09 12:13:17 -0700536 if (mService != null && isEnabled() && isValidDevice(device)) {
537 try {
538 return mService.getProtocolMode(device);
539 } catch (RemoteException e) {
540 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
541 return false;
542 }
543 }
544 if (mService == null) Log.w(TAG, "Proxy not attached to service");
545 return false;
546 }
547
548 /**
549 * Send Set_Protocol_Mode command to the connected HID input device.
550 *
551 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
552 *
553 * @param device Remote Bluetooth Device
554 * @return false on immediate error,
555 * true otherwise
556 * @hide
557 */
558 public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
559 if (DBG) log("setProtocolMode(" + device + ")");
560 if (mService != null && isEnabled() && isValidDevice(device)) {
561 try {
562 return mService.setProtocolMode(device, protocolMode);
563 } catch (RemoteException e) {
564 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
565 return false;
566 }
567 }
568 if (mService == null) Log.w(TAG, "Proxy not attached to service");
569 return false;
570 }
571
572 /**
573 * Send Get_Report command to the connected HID input device.
574 *
575 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
576 *
577 * @param device Remote Bluetooth Device
578 * @param reportType Report type
579 * @param reportId Report ID
580 * @param bufferSize Report receiving buffer size
581 * @return false on immediate error,
582 * true otherwise
583 * @hide
584 */
585 public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) {
Matthew Xie563e4142012-10-09 22:10:37 -0700586 if (VDBG) log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId + "bufferSize=" + bufferSize);
Priti Aghera349e62f2012-04-09 12:13:17 -0700587 if (mService != null && isEnabled() && isValidDevice(device)) {
588 try {
589 return mService.getReport(device, reportType, reportId, bufferSize);
590 } catch (RemoteException e) {
591 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
592 return false;
593 }
594 }
595 if (mService == null) Log.w(TAG, "Proxy not attached to service");
596 return false;
597 }
598
599 /**
600 * Send Set_Report command to the connected HID input device.
601 *
602 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
603 *
604 * @param device Remote Bluetooth Device
605 * @param reportType Report type
606 * @param report Report receiving buffer size
607 * @return false on immediate error,
608 * true otherwise
609 * @hide
610 */
611 public boolean setReport(BluetoothDevice device, byte reportType, String report) {
612 if (DBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
613 if (mService != null && isEnabled() && isValidDevice(device)) {
614 try {
615 return mService.setReport(device, reportType, report);
616 } catch (RemoteException e) {
617 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
618 return false;
619 }
620 }
621 if (mService == null) Log.w(TAG, "Proxy not attached to service");
622 return false;
623 }
624
625 /**
626 * Send Send_Data command to the connected HID input device.
627 *
628 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
629 *
630 * @param device Remote Bluetooth Device
631 * @param data Data to send
632 * @return false on immediate error,
633 * true otherwise
634 * @hide
635 */
636 public boolean sendData(BluetoothDevice device, String report) {
637 if (DBG) log("sendData(" + device + "), report=" + report);
638 if (mService != null && isEnabled() && isValidDevice(device)) {
639 try {
640 return mService.sendData(device, report);
641 } catch (RemoteException e) {
642 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
643 return false;
644 }
645 }
646 if (mService == null) Log.w(TAG, "Proxy not attached to service");
647 return false;
648 }
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700649 private static void log(String msg) {
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -0800650 Log.d(TAG, msg);
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700651 }
652}