summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java3
-rw-r--r--core/java/android/bluetooth/BluetoothDeviceProfileState.java18
-rw-r--r--core/java/android/bluetooth/BluetoothInputDevice.java320
-rw-r--r--core/java/android/bluetooth/BluetoothProfile.java5
-rw-r--r--core/java/android/bluetooth/BluetoothProfileState.java10
-rw-r--r--core/java/android/bluetooth/IBluetooth.aidl3
-rw-r--r--core/java/android/server/BluetoothEventLoop.java35
-rw-r--r--core/java/android/server/BluetoothInputProfileHandler.java19
-rw-r--r--core/java/android/server/BluetoothService.java82
-rw-r--r--core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java4
-rw-r--r--core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java207
11 files changed, 311 insertions, 395 deletions
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 4656e15..1f4fe80 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1049,6 +1049,9 @@ public final class BluetoothAdapter {
} else if (profile == BluetoothProfile.A2DP) {
BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
return true;
+ } else if (profile == BluetoothProfile.INPUT_DEVICE) {
+ BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener);
+ return true;
} else {
return false;
}
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index 6ec347f..116a068 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -136,17 +136,17 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
newState == BluetoothProfile.STATE_DISCONNECTED) {
sendMessage(TRANSITION_TO_STABLE);
}
- } else if (action.equals(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED)) {
- int newState = intent.getIntExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, 0);
+ } else if (action.equals(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED)) {
+ int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
int oldState =
- intent.getIntExtra(BluetoothInputDevice.EXTRA_PREVIOUS_INPUT_DEVICE_STATE, 0);
+ intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
- if (oldState == BluetoothInputDevice.STATE_CONNECTED &&
- newState == BluetoothInputDevice.STATE_DISCONNECTED) {
+ if (oldState == BluetoothProfile.STATE_CONNECTED &&
+ newState == BluetoothProfile.STATE_DISCONNECTED) {
sendMessage(DISCONNECT_HID_INCOMING);
}
- if (newState == BluetoothInputDevice.STATE_CONNECTED ||
- newState == BluetoothInputDevice.STATE_DISCONNECTED) {
+ if (newState == BluetoothProfile.STATE_CONNECTED ||
+ newState == BluetoothProfile.STATE_DISCONNECTED) {
sendMessage(TRANSITION_TO_STABLE);
}
} else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
@@ -194,7 +194,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
- filter.addAction(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED);
+ filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
mContext.registerReceiver(mBroadcastReceiver, filter);
@@ -286,7 +286,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
sendMessage(DISCONNECT_A2DP_OUTGOING);
deferMessage(message);
break;
- } else if (mService.getInputDeviceState(mDevice) !=
+ } else if (mService.getInputDeviceConnectionState(mDevice) !=
BluetoothInputDevice.STATE_DISCONNECTED) {
sendMessage(DISCONNECT_HID_OUTGOING);
deferMessage(message);
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index a70de59..df212a8 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,91 +27,88 @@ import android.util.Log;
import java.util.ArrayList;
import java.util.List;
+
/**
- * Public API for controlling the Bluetooth HID (Input Device) Profile
- *
- * BluetoothInputDevice is a proxy object used to make calls to Bluetooth Service
- * which handles the HID profile.
+ * This class provides the public APIs to control the Bluetooth Input
+ * Device Profile.
*
- * Creating a BluetoothInputDevice object will initiate a binding with the
- * Bluetooth service. Users of this object should call close() when they
- * are finished, so that this proxy object can unbind from the service.
+ *<p>BluetoothInputDevice is a proxy object for controlling the Bluetooth
+ * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothInputDevice proxy object.
*
- * Currently the Bluetooth service runs in the system server and this
- * proxy object will be immediately bound to the service on construction.
- *
- * @hide
+ *<p>Each method is protected with its appropriate permission.
+ *@hide
*/
-public final class BluetoothInputDevice {
+public final class BluetoothInputDevice implements BluetoothProfile {
private static final String TAG = "BluetoothInputDevice";
private static final boolean DBG = false;
- /** int extra for ACTION_INPUT_DEVICE_STATE_CHANGED */
- public static final String EXTRA_INPUT_DEVICE_STATE =
- "android.bluetooth.inputdevice.extra.INPUT_DEVICE_STATE";
- /** int extra for ACTION_INPUT_DEVICE_STATE_CHANGED */
- public static final String EXTRA_PREVIOUS_INPUT_DEVICE_STATE =
- "android.bluetooth.inputdevice.extra.PREVIOUS_INPUT_DEVICE_STATE";
-
- /** Indicates the state of an input device has changed.
- * This intent will always contain EXTRA_INPUT_DEVICE_STATE,
- * EXTRA_PREVIOUS_INPUT_DEVICE_STATE and BluetoothDevice.EXTRA_DEVICE
- * extras.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_INPUT_DEVICE_STATE_CHANGED =
- "android.bluetooth.inputdevice.action.INPUT_DEVICE_STATE_CHANGED";
-
- public static final int STATE_DISCONNECTED = 0;
- public static final int STATE_CONNECTING = 1;
- public static final int STATE_CONNECTED = 2;
- public static final int STATE_DISCONNECTING = 3;
-
- /**
- * Auto connection, incoming and outgoing connection are allowed at this
- * priority level.
- */
- public static final int PRIORITY_AUTO_CONNECT = 1000;
- /**
- * Incoming and outgoing connection are allowed at this priority level
- */
- public static final int PRIORITY_ON = 100;
- /**
- * Connections to the device are not allowed at this priority level.
- */
- public static final int PRIORITY_OFF = 0;
/**
- * Default priority level when the device is unpaired.
+ * Intent used to broadcast the change in connection state of the Input
+ * Device profile.
+ *
+ * <p>This intent will have 3 extras:
+ * <ul>
+ * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+ * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+ * </ul>
+ *
+ * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+ * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
+ * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
*/
- public static final int PRIORITY_UNDEFINED = -1;
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_CONNECTION_STATE_CHANGED =
+ "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
/**
* Return codes for the connect and disconnect Bluez / Dbus calls.
+ * @hide
*/
public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000;
+ /**
+ * @hide
+ */
public static final int INPUT_CONNECT_FAILED_ALREADY_CONNECTED = 5001;
+ /**
+ * @hide
+ */
public static final int INPUT_CONNECT_FAILED_ATTEMPT_FAILED = 5002;
+ /**
+ * @hide
+ */
public static final int INPUT_OPERATION_GENERIC_FAILURE = 5003;
+ /**
+ * @hide
+ */
public static final int INPUT_OPERATION_SUCCESS = 5004;
- private final IBluetooth mService;
- private final Context mContext;
+ private ServiceListener mServiceListener;
+ private BluetoothAdapter mAdapter;
+ private IBluetooth mService;
/**
* Create a BluetoothInputDevice proxy object for interacting with the local
- * Bluetooth Service which handle the HID profile.
- * @param c Context
+ * Bluetooth Service which handles the InputDevice profile
+ *
*/
- public BluetoothInputDevice(Context c) {
- mContext = c;
-
+ /*package*/ BluetoothInputDevice(Context mContext, ServiceListener l) {
IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
+ mServiceListener = l;
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
if (b != null) {
mService = IBluetooth.Stub.asInterface(b);
+ if (mServiceListener != null) {
+ mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, this);
+ }
} else {
Log.w(TAG, "Bluetooth Service not available!");
@@ -121,130 +118,151 @@ public final class BluetoothInputDevice {
}
}
- /** Initiate a connection to an Input device.
- *
- * This function returns false on error and true if the connection
- * attempt is being made.
- *
- * Listen for INPUT_DEVICE_STATE_CHANGED_ACTION to find out when the
- * connection is completed.
- * @param device Remote BT device.
- * @return false on immediate error, true otherwise
- * @hide
+ /**
+ * {@inheritDoc}
+ * @hide
*/
- public boolean connectInputDevice(BluetoothDevice device) {
- if (DBG) log("connectInputDevice(" + device + ")");
- try {
- return mService.connectInputDevice(device);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
+ public boolean connect(BluetoothDevice device) {
+ if (DBG) log("connect(" + device + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.connectInputDevice(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
}
- /** Initiate disconnect from an Input Device.
- * This function return false on error and true if the disconnection
- * attempt is being made.
- *
- * Listen for INPUT_DEVICE_STATE_CHANGED_ACTION to find out when
- * disconnect is completed.
- *
- * @param device Remote BT device.
- * @return false on immediate error, true otherwise
- * @hide
+ /**
+ * {@inheritDoc}
+ * @hide
*/
- public boolean disconnectInputDevice(BluetoothDevice device) {
- if (DBG) log("disconnectInputDevice(" + device + ")");
- try {
- return mService.disconnectInputDevice(device);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
+ public boolean disconnect(BluetoothDevice device) {
+ if (DBG) log("disconnect(" + device + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.disconnectInputDevice(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
}
- /** Check if a specified InputDevice is connected.
- *
- * @param device Remote BT device.
- * @return True if connected , false otherwise and on error.
- * @hide
+ /**
+ * {@inheritDoc}
*/
- public boolean isInputDeviceConnected(BluetoothDevice device) {
- if (DBG) log("isInputDeviceConnected(" + device + ")");
- int state = getInputDeviceState(device);
- if (state == STATE_CONNECTED) return true;
- return false;
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (DBG) log("getConnectedDevices()");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getConnectedInputDevices();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
}
- /** Check if any Input Device is connected.
- *
- * @return List of devices, empty List on error.
- * @hide
+ /**
+ * {@inheritDoc}
*/
- public List<BluetoothDevice> getConnectedInputDevices() {
- if (DBG) log("getConnectedInputDevices()");
- try {
- return mService.getConnectedInputDevices();
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return new ArrayList<BluetoothDevice>();
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ if (DBG) log("getDevicesMatchingStates()");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getInputDevicesMatchingConnectionStates(states);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
}
- /** Get the state of an Input Device.
- *
- * @param device Remote BT device.
- * @return The current state of the Input Device
- * @hide
+ /**
+ * {@inheritDoc}
*/
- public int getInputDeviceState(BluetoothDevice device) {
- if (DBG) log("getInputDeviceState(" + device + ")");
- try {
- return mService.getInputDeviceState(device);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return STATE_DISCONNECTED;
+ public int getConnectionState(BluetoothDevice device) {
+ if (DBG) log("getState(" + device + ")");
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
+ try {
+ return mService.getInputDeviceConnectionState(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return BluetoothProfile.STATE_DISCONNECTED;
}
/**
- * Set priority of an input device.
- *
- * Priority is a non-negative integer. Priority can take the following
- * values:
- * {@link PRIORITY_ON}, {@link PRIORITY_OFF}, {@link PRIORITY_AUTO_CONNECT}
- *
- * @param device Paired device.
- * @param priority Integer priority
- * @return true if priority is set, false on error
+ * {@inheritDoc}
+ * @hide
*/
- public boolean setInputDevicePriority(BluetoothDevice device, int priority) {
- if (DBG) log("setInputDevicePriority(" + device + ", " + priority + ")");
- try {
- return mService.setInputDevicePriority(device, priority);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
+ public boolean setPriority(BluetoothDevice device, int priority) {
+ if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
+ if (priority != BluetoothProfile.PRIORITY_OFF &&
+ priority != BluetoothProfile.PRIORITY_ON) {
+ return false;
+ }
+ try {
+ return mService.setInputDevicePriority(device, priority);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
}
/**
- * Get the priority associated with an Input Device.
- *
- * @param device Input Device
- * @return non-negative priority, or negative error code on error.
+ * {@inheritDoc}
+ * @hide
*/
- public int getInputDevicePriority(BluetoothDevice device) {
- if (DBG) log("getInputDevicePriority(" + device + ")");
- try {
- return mService.getInputDevicePriority(device);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return PRIORITY_OFF;
+ public int getPriority(BluetoothDevice device) {
+ if (DBG) log("getPriority(" + device + ")");
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
+ try {
+ return mService.getInputDevicePriority(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.PRIORITY_OFF;
+ }
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return BluetoothProfile.PRIORITY_OFF;
+ }
+
+ private boolean isEnabled() {
+ if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
+ return false;
+ }
+
+ private boolean isValidDevice(BluetoothDevice device) {
+ if (device == null) return false;
+
+ if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+ return false;
}
private static void log(String msg) {
- Log.d(TAG, msg);
+ Log.d(TAG, msg);
}
}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index ef80195..1ffee72 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -62,6 +62,11 @@ public interface BluetoothProfile {
* A2DP profile.
*/
public static final int A2DP = 2;
+ /**
+ * Input Device Profile
+ * @hide
+ */
+ public static final int INPUT_DEVICE = 3;
/**
* Default priority for devices that we try to auto-connect to and
diff --git a/core/java/android/bluetooth/BluetoothProfileState.java b/core/java/android/bluetooth/BluetoothProfileState.java
index 3f36926..18060a0 100644
--- a/core/java/android/bluetooth/BluetoothProfileState.java
+++ b/core/java/android/bluetooth/BluetoothProfileState.java
@@ -72,10 +72,10 @@ public class BluetoothProfileState extends HierarchicalStateMachine {
newState == BluetoothProfile.STATE_DISCONNECTED)) {
sendMessage(TRANSITION_TO_STABLE);
}
- } else if (action.equals(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED)) {
- int newState = intent.getIntExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, 0);
- if (mProfile == HID && (newState == BluetoothInputDevice.STATE_CONNECTED ||
- newState == BluetoothInputDevice.STATE_DISCONNECTED)) {
+ } else if (action.equals(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED)) {
+ int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
+ if (mProfile == HID && (newState == BluetoothProfile.STATE_CONNECTED ||
+ newState == BluetoothProfile.STATE_DISCONNECTED)) {
sendMessage(TRANSITION_TO_STABLE);
}
} else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
@@ -96,7 +96,7 @@ public class BluetoothProfileState extends HierarchicalStateMachine {
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
- filter.addAction(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED);
+ filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
context.registerReceiver(mBroadcastReceiver, filter);
}
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index f3e73cf..69fb06a 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -85,7 +85,8 @@ interface IBluetooth
boolean connectInputDevice(in BluetoothDevice device);
boolean disconnectInputDevice(in BluetoothDevice device);
List<BluetoothDevice> getConnectedInputDevices();
- int getInputDeviceState(in BluetoothDevice device);
+ List<BluetoothDevice> getInputDevicesMatchingConnectionStates(in int[] states);
+ int getInputDeviceConnectionState(in BluetoothDevice device);
boolean setInputDevicePriority(in BluetoothDevice device, int priority);
int getInputDevicePriority(in BluetoothDevice device);
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 3316ea5..c0b3cc8 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -57,6 +57,7 @@ class BluetoothEventLoop {
private final BluetoothService mBluetoothService;
private final BluetoothAdapter mAdapter;
private BluetoothA2dp mA2dp;
+ private BluetoothInputDevice mInputDevice;
private final Context mContext;
// The WakeLock is used for bringing up the LCD during a pairing request
// from remote device when Android is in Suspend state.
@@ -125,15 +126,24 @@ class BluetoothEventLoop {
/*package*/ void getProfileProxy() {
mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.A2DP);
+ mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.INPUT_DEVICE);
}
private BluetoothProfile.ServiceListener mProfileServiceListener =
new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
- mA2dp = (BluetoothA2dp) proxy;
+ if (profile == BluetoothProfile.A2DP) {
+ mA2dp = (BluetoothA2dp) proxy;
+ } else if (profile == BluetoothProfile.INPUT_DEVICE) {
+ mInputDevice = (BluetoothInputDevice) proxy;
+ }
}
public void onServiceDisconnected(int profile) {
- mA2dp = null;
+ if (profile == BluetoothProfile.A2DP) {
+ mA2dp = null;
+ } else if (profile == BluetoothProfile.INPUT_DEVICE) {
+ mInputDevice = null;
+ }
}
};
@@ -651,10 +661,9 @@ class BluetoothEventLoop {
} else {
Log.i(TAG, "Rejecting incoming A2DP / AVRCP connection from " + address);
}
- } else if (BluetoothUuid.isInputDevice(uuid) && !isOtherInputDeviceConnected(address)) {
- BluetoothInputDevice inputDevice = new BluetoothInputDevice(mContext);
- authorized = inputDevice.getInputDevicePriority(device) >
- BluetoothInputDevice.PRIORITY_OFF;
+ } else if (mInputDevice != null && BluetoothUuid.isInputDevice(uuid)) {
+ // We can have more than 1 input device connected.
+ authorized = mInputDevice.getPriority(device) > BluetoothInputDevice.PRIORITY_OFF;
if (authorized) {
Log.i(TAG, "Allowing incoming HID connection from " + address);
} else {
@@ -669,18 +678,6 @@ class BluetoothEventLoop {
return authorized;
}
- private boolean isOtherInputDeviceConnected(String address) {
- List<BluetoothDevice> devices =
- mBluetoothService.lookupInputDevicesMatchingStates(new int[] {
- BluetoothInputDevice.STATE_CONNECTING,
- BluetoothInputDevice.STATE_CONNECTED});
-
- for (BluetoothDevice device : devices) {
- if (!device.getAddress().equals(address)) return true;
- }
- return false;
- }
-
private boolean onAgentOutOfBandDataAvailable(String objectPath) {
if (!mBluetoothService.isEnabled()) return false;
@@ -758,7 +755,7 @@ class BluetoothEventLoop {
boolean connected = false;
BluetoothDevice device = mAdapter.getRemoteDevice(address);
- int state = mBluetoothService.getInputDeviceState(device);
+ int state = mBluetoothService.getInputDeviceConnectionState(device);
if (state == BluetoothInputDevice.STATE_CONNECTING) {
if (result == BluetoothInputDevice.INPUT_CONNECT_FAILED_ALREADY_CONNECTED) {
connected = true;
diff --git a/core/java/android/server/BluetoothInputProfileHandler.java b/core/java/android/server/BluetoothInputProfileHandler.java
index 7ffa5ae..cdc0f2d 100644
--- a/core/java/android/server/BluetoothInputProfileHandler.java
+++ b/core/java/android/server/BluetoothInputProfileHandler.java
@@ -64,7 +64,7 @@ final class BluetoothInputProfileHandler {
BluetoothDeviceProfileState state) {
String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
if (objectPath == null ||
- getInputDeviceState(device) != BluetoothInputDevice.STATE_DISCONNECTED ||
+ getInputDeviceConnectionState(device) != BluetoothInputDevice.STATE_DISCONNECTED ||
getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_OFF) {
return false;
}
@@ -92,7 +92,7 @@ final class BluetoothInputProfileHandler {
BluetoothDeviceProfileState state) {
String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
if (objectPath == null ||
- getInputDeviceState(device) == BluetoothInputDevice.STATE_DISCONNECTED) {
+ getInputDeviceConnectionState(device) == BluetoothInputDevice.STATE_DISCONNECTED) {
return false;
}
if (state != null) {
@@ -115,7 +115,7 @@ final class BluetoothInputProfileHandler {
return true;
}
- synchronized int getInputDeviceState(BluetoothDevice device) {
+ synchronized int getInputDeviceConnectionState(BluetoothDevice device) {
if (mInputDevices.get(device) == null) {
return BluetoothInputDevice.STATE_DISCONNECTED;
}
@@ -128,6 +128,11 @@ final class BluetoothInputProfileHandler {
return devices;
}
+ synchronized List<BluetoothDevice> getInputDevicesMatchingConnectionStates(int[] states) {
+ List<BluetoothDevice> devices = lookupInputDevicesMatchingStates(states);
+ return devices;
+ }
+
synchronized int getInputDevicePriority(BluetoothDevice device) {
return Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
@@ -147,7 +152,7 @@ final class BluetoothInputProfileHandler {
List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>();
for (BluetoothDevice device: mInputDevices.keySet()) {
- int inputDeviceState = getInputDeviceState(device);
+ int inputDeviceState = getInputDeviceConnectionState(device);
for (int state : states) {
if (state == inputDeviceState) {
inputDevices.add(device);
@@ -178,10 +183,10 @@ final class BluetoothInputProfileHandler {
setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_AUTO_CONNECT);
}
- Intent intent = new Intent(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED);
+ Intent intent = new Intent(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
- intent.putExtra(BluetoothInputDevice.EXTRA_PREVIOUS_INPUT_DEVICE_STATE, prevState);
- intent.putExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, state);
+ intent.putExtra(BluetoothInputDevice.EXTRA_PREVIOUS_STATE, prevState);
+ intent.putExtra(BluetoothInputDevice.EXTRA_STATE, state);
mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
debugLog("InputDevice state : device: " + device + " State:" + prevState + "->" + state);
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index a295de5..70aaf0a 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -31,6 +31,7 @@ import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDeviceProfileState;
import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothInputDevice;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProfileState;
@@ -83,6 +84,7 @@ public class BluetoothService extends IBluetooth.Stub {
private int mNativeData;
private BluetoothEventLoop mEventLoop;
private BluetoothHeadset mBluetoothHeadset;
+ private BluetoothInputDevice mInputDevice;
private boolean mIsAirplaneSensitive;
private boolean mIsAirplaneToggleable;
private int mBluetoothState;
@@ -2078,6 +2080,8 @@ public class BluetoothService extends IBluetooth.Stub {
mAdapter.getProfileProxy(mContext,
mBluetoothProfileServiceListener, BluetoothProfile.HEADSET);
+ mAdapter.getProfileProxy(mContext,
+ mBluetoothProfileServiceListener, BluetoothProfile.INPUT_DEVICE);
pw.println("\n--Known devices--");
for (String address : mDeviceProperties.keySet()) {
@@ -2119,8 +2123,17 @@ public class BluetoothService extends IBluetooth.Stub {
}
}
- // Rather not do this from here, but no-where else and I need this
- // dump
+ dumpHeadsetProfile(pw);
+ dumpInputDeviceProfile(pw);
+
+ pw.println("\n--Application Service Records--");
+ for (Integer handle : mServiceRecordToPid.keySet()) {
+ Integer pid = mServiceRecordToPid.get(handle);
+ pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle));
+ }
+ }
+
+ private void dumpHeadsetProfile(PrintWriter pw) {
pw.println("\n--Headset Service--");
if (mBluetoothHeadset != null) {
List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
@@ -2158,24 +2171,60 @@ public class BluetoothService extends IBluetooth.Stub {
pw.println("SCO audio connected to device:" + device);
}
}
-
- mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
}
+ mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
+ }
- pw.println("\n--Application Service Records--");
- for (Integer handle : mServiceRecordToPid.keySet()) {
- Integer pid = mServiceRecordToPid.get(handle);
- pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle));
+ private void dumpInputDeviceProfile(PrintWriter pw) {
+ pw.println("\n--Bluetooth Service- Input Device Profile");
+ if (mInputDevice != null) {
+ List<BluetoothDevice> deviceList = mInputDevice.getConnectedDevices();
+ if (deviceList.size() == 0) {
+ pw.println("\nNo input devices connected--");
+ } else {
+ pw.println("\nNumber of connected devices:" + deviceList.size());
+ BluetoothDevice device = deviceList.get(0);
+ pw.println("getConnectedDevices[0] = " + device);
+ pw.println("Priority of Connected device = " + mInputDevice.getPriority(device));
+
+ switch (mInputDevice.getConnectionState(device)) {
+ case BluetoothInputDevice.STATE_CONNECTING:
+ pw.println("getConnectionState() = STATE_CONNECTING");
+ break;
+ case BluetoothInputDevice.STATE_CONNECTED:
+ pw.println("getConnectionState() = STATE_CONNECTED");
+ break;
+ case BluetoothInputDevice.STATE_DISCONNECTING:
+ pw.println("getConnectionState() = STATE_DISCONNECTING");
+ break;
+ }
+ }
+ deviceList.clear();
+ deviceList = mInputDevice.getDevicesMatchingConnectionStates(new int[] {
+ BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
+ pw.println("--Connected and Disconnected input devices");
+ for (BluetoothDevice device: deviceList) {
+ pw.println(device);
+ }
}
+ mAdapter.closeProfileProxy(BluetoothProfile.INPUT_DEVICE, mBluetoothHeadset);
}
private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
- mBluetoothHeadset = (BluetoothHeadset) proxy;
- }
+ if (profile == BluetoothProfile.HEADSET) {
+ mBluetoothHeadset = (BluetoothHeadset) proxy;
+ } else if (profile == BluetoothProfile.INPUT_DEVICE) {
+ mInputDevice = (BluetoothInputDevice) proxy;
+ }
+ }
public void onServiceDisconnected(int profile) {
- mBluetoothHeadset = null;
+ if (profile == BluetoothProfile.HEADSET) {
+ mBluetoothHeadset = null;
+ } else if (profile == BluetoothProfile.INPUT_DEVICE) {
+ mInputDevice = null;
+ }
}
};
@@ -2311,9 +2360,9 @@ public class BluetoothService extends IBluetooth.Stub {
return mBluetoothInputProfileHandler.disconnectInputDeviceInternal(device);
}
- public synchronized int getInputDeviceState(BluetoothDevice device) {
+ public synchronized int getInputDeviceConnectionState(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBluetoothInputProfileHandler.getInputDeviceState(device);
+ return mBluetoothInputProfileHandler.getInputDeviceConnectionState(device);
}
@@ -2322,6 +2371,13 @@ public class BluetoothService extends IBluetooth.Stub {
return mBluetoothInputProfileHandler.getConnectedInputDevices();
}
+ public synchronized List<BluetoothDevice> getInputDevicesMatchingConnectionStates(
+ int[] states) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mBluetoothInputProfileHandler.getInputDevicesMatchingConnectionStates(states);
+ }
+
+
public synchronized int getInputDevicePriority(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
return mBluetoothInputProfileHandler.getInputDevicePriority(device);
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
index 96b028a..672f252 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
@@ -250,8 +250,8 @@ public class BluetoothStressTest extends InstrumentationTestCase {
for (int i = 0; i < iterations; i++) {
mTestUtils.writeOutput("connectInput iteration " + (i + 1) + " of " + iterations);
- mTestUtils.connectInput(adapter, device);
- mTestUtils.disconnectInput(adapter, device);
+ mTestUtils.connectProfile(adapter, device, BluetoothProfile.INPUT_DEVICE);
+ mTestUtils.disconnectProfile(adapter, device, BluetoothProfile.INPUT_DEVICE);
}
mTestUtils.unpair(adapter, device);
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
index effed76..35210e5 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
@@ -238,6 +238,9 @@ public class BluetoothTestUtils extends Assert {
case BluetoothProfile.HEADSET:
mConnectionAction = BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED;
break;
+ case BluetoothProfile.INPUT_DEVICE:
+ mConnectionAction = BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED;
+ break;
default:
mConnectionAction = null;
}
@@ -270,47 +273,6 @@ public class BluetoothTestUtils extends Assert {
}
}
- private class ConnectInputReceiver extends FlagReceiver {
- private static final int STATE_DISCONNECTED_FLAG = 1;
- private static final int STATE_CONNECTING_FLAG = 1 << 1;
- private static final int STATE_CONNECTED_FLAG = 1 << 2;
- private static final int STATE_DISCONNECTING_FLAG = 1 << 3;
-
- private BluetoothDevice mDevice;
-
- public ConnectInputReceiver(BluetoothDevice device, int expectedFlags) {
- super(expectedFlags);
-
- mDevice = device;
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) {
- return;
- }
-
- if (BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED.equals(intent.getAction())) {
- int state = intent.getIntExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, -1);
- assertNotSame(-1, state);
- switch (state) {
- case BluetoothInputDevice.STATE_DISCONNECTED:
- setFiredFlag(STATE_DISCONNECTED_FLAG);
- break;
- case BluetoothInputDevice.STATE_CONNECTING:
- setFiredFlag(STATE_CONNECTING_FLAG);
- break;
- case BluetoothInputDevice.STATE_CONNECTED:
- setFiredFlag(STATE_CONNECTED_FLAG);
- break;
- case BluetoothInputDevice.STATE_DISCONNECTING:
- setFiredFlag(STATE_DISCONNECTING_FLAG);
- break;
- }
- }
- }
- }
-
private class ConnectPanReceiver extends FlagReceiver {
private static final int STATE_DISCONNECTED_FLAG = 1;
private static final int STATE_CONNECTING_FLAG = 1 << 1;
@@ -366,6 +328,9 @@ public class BluetoothTestUtils extends Assert {
case BluetoothProfile.HEADSET:
mHeadset = (BluetoothHeadset) proxy;
break;
+ case BluetoothProfile.INPUT_DEVICE:
+ mInput = (BluetoothInputDevice) proxy;
+ break;
}
}
}
@@ -379,6 +344,9 @@ public class BluetoothTestUtils extends Assert {
case BluetoothProfile.HEADSET:
mHeadset = null;
break;
+ case BluetoothProfile.INPUT_DEVICE:
+ mInput = null;
+ break;
}
}
}
@@ -393,6 +361,7 @@ public class BluetoothTestUtils extends Assert {
private Context mContext;
private BluetoothA2dp mA2dp;
private BluetoothHeadset mHeadset;
+ private BluetoothInputDevice mInput;
/**
* Creates a utility instance for testing Bluetooth.
@@ -1078,142 +1047,6 @@ public class BluetoothTestUtils extends Assert {
}
/**
- * Connects the local device with a remote HID device and checks to make sure that the profile
- * is connected and that the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- */
- public void connectInput(BluetoothAdapter adapter, BluetoothDevice device) {
- int mask = (ConnectInputReceiver.STATE_CONNECTING_FLAG
- | ConnectInputReceiver.STATE_CONNECTED_FLAG);
- long start = -1;
-
- if (!adapter.isEnabled()) {
- fail(String.format("connectInput() bluetooth not enabled: device=%s", device));
- }
-
- if (!adapter.getBondedDevices().contains(device)) {
- fail(String.format("connectInput() device not paired: device=%s", device));
- }
-
- BluetoothInputDevice inputDevice = new BluetoothInputDevice(mContext);
- assertNotNull(inputDevice);
- ConnectInputReceiver receiver = getConnectInputReceiver(device, mask);
-
- int state = inputDevice.getInputDeviceState(device);
- switch (state) {
- case BluetoothInputDevice.STATE_CONNECTED:
- removeReceiver(receiver);
- return;
- case BluetoothInputDevice.STATE_CONNECTING:
- mask = 0; // Don't check for received intents since we might have missed them.
- break;
- case BluetoothInputDevice.STATE_DISCONNECTED:
- case BluetoothInputDevice.STATE_DISCONNECTING:
- start = System.currentTimeMillis();
- assertTrue(inputDevice.connectInputDevice(device));
- break;
- default:
- removeReceiver(receiver);
- fail(String.format("connectInput() invalid state: device=%s, state=%d", device,
- state));
- }
-
- long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
- state = inputDevice.getInputDeviceState(device);
- if (state == BluetoothInputDevice.STATE_CONNECTED
- && (receiver.getFiredFlags() & mask) == mask) {
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("connectInput() completed in %d ms: device=%s",
- (finish - start), device));
- } else {
- writeOutput(String.format("connectInput() completed: device=%s", device));
- }
- removeReceiver(receiver);
- return;
- }
- sleep(POLL_TIME);
- }
-
- int firedFlags = receiver.getFiredFlags();
- removeReceiver(receiver);
- fail(String.format("connectInput() timeout: device=%s, state=%d (expected %d), "
- + "flags=0x%x (expected 0x%s)", device, state, BluetoothInputDevice.STATE_CONNECTED,
- firedFlags, mask));
- }
-
- /**
- * Disconnects the local device with a remote HID device and checks to make sure that the
- * profile is connected and that the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- */
- public void disconnectInput(BluetoothAdapter adapter, BluetoothDevice device) {
- int mask = (ConnectInputReceiver.STATE_DISCONNECTING_FLAG
- | ConnectInputReceiver.STATE_DISCONNECTED_FLAG);
- long start = -1;
-
- if (!adapter.isEnabled()) {
- fail(String.format("disconnectInput() bluetooth not enabled: device=%s", device));
- }
-
- if (!adapter.getBondedDevices().contains(device)) {
- fail(String.format("disconnectInput() device not paired: device=%s", device));
- }
-
- BluetoothInputDevice inputDevice = new BluetoothInputDevice(mContext);
- assertNotNull(inputDevice);
- ConnectInputReceiver receiver = getConnectInputReceiver(device, mask);
-
- int state = inputDevice.getInputDeviceState(device);
- switch (state) {
- case BluetoothInputDevice.STATE_CONNECTED:
- case BluetoothInputDevice.STATE_CONNECTING:
- start = System.currentTimeMillis();
- assertTrue(inputDevice.disconnectInputDevice(device));
- break;
- case BluetoothInputDevice.STATE_DISCONNECTED:
- removeReceiver(receiver);
- return;
- case BluetoothInputDevice.STATE_DISCONNECTING:
- mask = 0; // Don't check for received intents since we might have missed them.
- break;
- default:
- removeReceiver(receiver);
- fail(String.format("disconnectInput() invalid state: device=%s, state=%d", device,
- state));
- }
-
- long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
- state = inputDevice.getInputDeviceState(device);
- if (state == BluetoothInputDevice.STATE_DISCONNECTED
- && (receiver.getFiredFlags() & mask) == mask) {
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("disconnectInput() completed in %d ms: device=%s",
- (finish - start), device));
- } else {
- writeOutput(String.format("disconnectInput() completed: device=%s", device));
- }
- removeReceiver(receiver);
- return;
- }
- sleep(POLL_TIME);
- }
-
- int firedFlags = receiver.getFiredFlags();
- removeReceiver(receiver);
- fail(String.format("disconnectInput() timeout: device=%s, state=%d (expected %d), "
- + "flags=0x%x (expected 0x%s)", device, state,
- BluetoothInputDevice.STATE_DISCONNECTED, firedFlags, mask));
- }
-
- /**
* Connects the PANU to a remote NAP and checks to make sure that the PANU is connected and that
* the correct actions were broadcast.
*
@@ -1478,21 +1311,14 @@ public class BluetoothTestUtils extends Assert {
int expectedFlags) {
String[] actions = {
BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED,
- BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED};
+ BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED,
+ BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED};
ConnectProfileReceiver receiver = new ConnectProfileReceiver(device, profile,
expectedFlags);
addReceiver(receiver, actions);
return receiver;
}
- private ConnectInputReceiver getConnectInputReceiver(BluetoothDevice device,
- int expectedFlags) {
- String[] actions = {BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED};
- ConnectInputReceiver receiver = new ConnectInputReceiver(device, expectedFlags);
- addReceiver(receiver, actions);
- return receiver;
- }
-
private ConnectPanReceiver getConnectPanReceiver(BluetoothDevice device, int role,
int expectedFlags) {
String[] actions = {BluetoothPan.ACTION_PAN_STATE_CHANGED};
@@ -1511,15 +1337,20 @@ public class BluetoothTestUtils extends Assert {
long s = System.currentTimeMillis();
switch (profile) {
case BluetoothProfile.A2DP:
- while (mA2dp != null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
+ while (mA2dp == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
sleep(POLL_TIME);
}
return mA2dp;
case BluetoothProfile.HEADSET:
- while (mHeadset != null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
+ while (mHeadset == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
sleep(POLL_TIME);
}
return mHeadset;
+ case BluetoothProfile.INPUT_DEVICE:
+ while (mInput == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
+ sleep(POLL_TIME);
+ }
+ return mInput;
default:
return null;
}