diff options
| author | Nick Pelly <npelly@google.com> | 2009-10-07 07:44:03 +0200 |
|---|---|---|
| committer | Nick Pelly <npelly@google.com> | 2009-10-07 23:25:24 +0200 |
| commit | 07b84cb5bb5283352a27cc0cf651586ed00035a0 (patch) | |
| tree | 62ef30e6b0c78badc1cc88ff0abc919e1abff5c2 /framework/java/android/bluetooth/BluetoothAdapter.java | |
| parent | 1e79198aafef8cde937694e6fdbd863acf4f7b8a (diff) | |
Encourage developers to connect RFCOMM by UUID instead of Channel.
Hide createRfcommSocket(int channel)
Add createRfcommSocketWithServiceRecord(UUID uuid)
Rename listenUsingRfcomm(String,UUID) -> listenUsingRfcommWithServiceRecord(..)
Now we have a complete API for developers to make peer-peer RFCOMM connections
with hard-coding the limited (30) RFCOMM channels, instead using SDP lookup
of an UUID.
This commit addresses two serious bugs:
- Do not throw IOException on accepting an incoming RFCOMM connection with
BluetoothSocket. This was a regression from commit ee1402d8d697be3a
- Workaround failure of bluez to update SDP cache when channel changes by
trying to use the same RFCOMM channel on the server every time, instead
of picking server channels randomly. This is a pretty ugly workaround,
and we are still trying to fix the caching issue - but with this
workaround we are at least shippable and apps will work at least until
they start colliding on the 30 RFCOMM channels.
DrNo: eastham
Bug: 2158900
Joke: What did the digital watch say to his mom? "Look mom no hands."
Change-Id: Ia4879943b83afac06b6f1a3f2391cf1628afce7d
Diffstat (limited to 'framework/java/android/bluetooth/BluetoothAdapter.java')
| -rw-r--r-- | framework/java/android/bluetooth/BluetoothAdapter.java | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index c6a0619cf8..8ce911de37 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -31,6 +31,7 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.Random; import java.util.Set; +import java.util.UUID; /** * Represents the local Bluetooth adapter. @@ -564,8 +565,16 @@ public final class BluetoothAdapter { } /** - * Randomly picks RFCOMM channels until none are left. + * Picks RFCOMM channels until none are left. * Avoids reserved channels. + * Ideally we would pick random channels, but in the current implementation + * we start with the channel that is the hash of the UUID, and try every + * available channel from there. This means that in most cases a given + * uuid will use the same channel. This is a workaround for a Bluez SDP + * bug where we are not updating the cache when the channel changes for a + * uuid. + * TODO: Fix the Bluez SDP caching bug, and go back to random channel + * selection */ private static class RfcommChannelPicker { private static final int[] RESERVED_RFCOMM_CHANNELS = new int[] { @@ -579,7 +588,9 @@ public final class BluetoothAdapter { private final LinkedList<Integer> mChannels; // local list of channels left to try - public RfcommChannelPicker() { + private final UUID mUuid; + + public RfcommChannelPicker(UUID uuid) { synchronized (RfcommChannelPicker.class) { if (sChannels == null) { // lazy initialization of non-reserved rfcomm channels @@ -594,13 +605,21 @@ public final class BluetoothAdapter { } mChannels = (LinkedList<Integer>)sChannels.clone(); } + mUuid = uuid; } - /* Returns next random channel, or -1 if we're out */ + /* Returns next channel, or -1 if we're out */ public int nextChannel() { - if (mChannels.size() == 0) { - return -1; + int channel = mUuid.hashCode(); // always pick the same channel to try first + Integer channelInt; + while (mChannels.size() > 0) { + channelInt = new Integer(channel); + if (mChannels.remove(channelInt)) { + return channel; + } + channel = (channel % BluetoothSocket.MAX_RFCOMM_CHANNEL) + 1; } - return mChannels.remove(sRandom.nextInt(mChannels.size())); + + return -1; } } @@ -644,6 +663,8 @@ public final class BluetoothAdapter { * can use the same UUID to query our SDP server and discover which channel * to connect to. This SDP record will be removed when this socket is * closed, or if this application closes unexpectedly. + * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to + * connect to this socket from another device using the same {@link UUID}. * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * @param name service name for SDP record * @param uuid uuid for SDP record @@ -651,9 +672,9 @@ public final class BluetoothAdapter { * @throws IOException on error, for example Bluetooth not available, or * insufficient permissions, or channel in use. */ - public BluetoothServerSocket listenUsingRfcomm(String name, ParcelUuid uuid) + public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid) throws IOException { - RfcommChannelPicker picker = new RfcommChannelPicker(); + RfcommChannelPicker picker = new RfcommChannelPicker(uuid); BluetoothServerSocket socket; int channel; @@ -687,7 +708,8 @@ public final class BluetoothAdapter { int handle = -1; try { - handle = mService.addRfcommServiceRecord(name, uuid, channel, new Binder()); + handle = mService.addRfcommServiceRecord(name, new ParcelUuid(uuid), channel, + new Binder()); } catch (RemoteException e) {Log.e(TAG, "", e);} if (handle == -1) { try { |
