2929import android .os .RemoteException ;
3030import android .util .Log ;
3131
32- import java .io .FileDescriptor ;
3332import java .io .IOException ;
3433import java .util .ArrayList ;
3534import java .util .HashMap ;
3635import java .util .List ;
3736import java .util .Map .Entry ;
37+ import java .util .concurrent .atomic .AtomicInteger ;
3838
3939/**
4040 * This handles all the operations on the Bluetooth Health profile.
@@ -58,6 +58,7 @@ final class BluetoothHealthProfileHandler {
5858 private static final int MESSAGE_REGISTER_APPLICATION = 0 ;
5959 private static final int MESSAGE_UNREGISTER_APPLICATION = 1 ;
6060 private static final int MESSAGE_CONNECT_CHANNEL = 2 ;
61+ private static final AtomicInteger sChannelId = new AtomicInteger ();
6162
6263 class HealthChannel {
6364 private ParcelFileDescriptor mChannelFd ;
@@ -67,6 +68,7 @@ class HealthChannel {
6768 private BluetoothHealthAppConfiguration mConfig ;
6869 private int mState ;
6970 private int mChannelType ;
71+ private int mId ;
7072
7173 HealthChannel (BluetoothDevice device , BluetoothHealthAppConfiguration config ,
7274 ParcelFileDescriptor fd , boolean mainChannel , String channelPath ) {
@@ -76,6 +78,7 @@ class HealthChannel {
7678 mDevice = device ;
7779 mConfig = config ;
7880 mState = BluetoothHealth .STATE_CHANNEL_DISCONNECTED ;
81+ mId = getChannelId ();
7982 }
8083 }
8184
@@ -117,7 +120,7 @@ public void handleMessage(Message msg) {
117120 for (HealthChannel chan : mHealthChannels ) {
118121 if (chan .mConfig .equals (unregisterApp ) &&
119122 chan .mState != BluetoothHealth .STATE_CHANNEL_DISCONNECTED ) {
120- disconnectChannel (chan .mDevice , unregisterApp , chan .hashCode () );
123+ disconnectChannel (chan .mDevice , unregisterApp , chan .mId );
121124 }
122125 }
123126
@@ -141,11 +144,11 @@ public void handleMessage(Message msg) {
141144 String channelType = getStringChannelType (chan .mChannelType );
142145
143146 if (!mBluetoothService .createChannelNative (deviceObjectPath , configPath ,
144- channelType , chan .hashCode () )) {
147+ channelType , chan .mId )) {
145148 int prevState = chan .mState ;
146149 int state = BluetoothHealth .STATE_CHANNEL_DISCONNECTED ;
147150 callHealthChannelCallback (chan .mConfig , chan .mDevice , prevState , state , null ,
148- chan .hashCode () );
151+ chan .mId );
149152 mHealthChannels .remove (chan );
150153 }
151154 }
@@ -216,7 +219,7 @@ boolean connectChannel(BluetoothDevice device,
216219
217220 int prevState = BluetoothHealth .STATE_CHANNEL_DISCONNECTED ;
218221 int state = BluetoothHealth .STATE_CHANNEL_CONNECTING ;
219- callHealthChannelCallback (config , device , prevState , state , null , chan .hashCode () );
222+ callHealthChannelCallback (config , device , prevState , state , null , chan .mId );
220223
221224 Message msg = mHandler .obtainMessage (MESSAGE_CONNECT_CHANNEL );
222225 msg .obj = chan ;
@@ -245,6 +248,23 @@ private String getStringRole(int role) {
245248 }
246249 }
247250
251+ private int getChannelId () {
252+ // The function doesn't need to be synchronized, as the health profile handler
253+ // will only allow one health channel object creation at a time.
254+ // In the worst case the while loop will have to break out at some point of
255+ // time, because only a limited number of L2CAP channels are possible.
256+ int id ;
257+ boolean found ;
258+ do {
259+ id = sChannelId .incrementAndGet ();
260+ found = false ;
261+ for (HealthChannel chan : mHealthChannels ) {
262+ if (chan .mId == id ) found = true ;
263+ }
264+ } while (found );
265+ return id ;
266+ }
267+
248268 boolean disconnectChannel (BluetoothDevice device ,
249269 BluetoothHealthAppConfiguration config , int id ) {
250270 HealthChannel chan = findChannelById (id );
@@ -260,14 +280,14 @@ boolean disconnectChannel(BluetoothDevice device,
260280 int prevState = chan .mState ;
261281 chan .mState = BluetoothHealth .STATE_CHANNEL_DISCONNECTING ;
262282 callHealthChannelCallback (config , device , prevState , chan .mState ,
263- null , chan .hashCode () );
283+ null , chan .mId );
264284
265285 if (!mBluetoothService .destroyChannelNative (deviceObjectPath , chan .mChannelPath ,
266- chan .hashCode () )) {
286+ chan .mId )) {
267287 prevState = chan .mState ;
268288 chan .mState = BluetoothHealth .STATE_CHANNEL_CONNECTED ;
269289 callHealthChannelCallback (config , device , prevState , chan .mState ,
270- chan .mChannelFd , chan .hashCode () );
290+ chan .mChannelFd , chan .mId );
271291 return false ;
272292 } else {
273293 return true ;
@@ -276,7 +296,7 @@ boolean disconnectChannel(BluetoothDevice device,
276296
277297 private HealthChannel findChannelById (int id ) {
278298 for (HealthChannel chan : mHealthChannels ) {
279- if (chan .hashCode () == id ) return chan ;
299+ if (chan .mId == id ) return chan ;
280300 }
281301 return null ;
282302 }
@@ -434,7 +454,7 @@ private BluetoothHealthAppConfiguration findHealthApplication(
434454 fd = mBluetoothService .getChannelFdNative (channelPath );
435455 if (fd == null ) {
436456 errorLog ("Error obtaining fd for channel:" + channelPath );
437- disconnectChannel (device , config , channel .hashCode () );
457+ disconnectChannel (device , config , channel .mId );
438458 return ;
439459 }
440460 boolean mainChannel =
@@ -467,7 +487,7 @@ private BluetoothHealthAppConfiguration findHealthApplication(
467487 }
468488 channel .mState = state ;
469489 callHealthChannelCallback (config , device , prevState , state , channel .mChannelFd ,
470- channel .hashCode () );
490+ channel .mId );
471491 }
472492
473493 private void callHealthChannelCallback (BluetoothHealthAppConfiguration config ,
0 commit comments