mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-16 15:41:16 +01:00
code cleanup: make treads own their queue datastructures, use methods
to stop them, etc. Heading toward making it easier to detect when the BT stack is hosed and user needs to be warned or told to get a better phone.
This commit is contained in:
parent
3bda56420c
commit
ac2ac47aed
1 changed files with 127 additions and 90 deletions
|
@ -121,13 +121,12 @@ public class BTService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
private BluetoothAdapter m_adapter;
|
private BluetoothAdapter m_adapter;
|
||||||
private LinkedBlockingQueue<BTQueueElem> m_queue;
|
|
||||||
private static HashMap<String,String> s_names =
|
private static HashMap<String,String> s_names =
|
||||||
new HashMap<String, String>();
|
new HashMap<String, String>();
|
||||||
private static HashMap<String,int[]> s_devGames;
|
private static HashMap<String,int[]> s_devGames;
|
||||||
private BTMsgSink m_btMsgSink;
|
private BTMsgSink m_btMsgSink;
|
||||||
private Thread m_listener;
|
private BTListenerThread m_listener;
|
||||||
private Thread m_sender;
|
private BTSenderThread m_sender;
|
||||||
|
|
||||||
public static boolean BTEnabled()
|
public static boolean BTEnabled()
|
||||||
{
|
{
|
||||||
|
@ -221,7 +220,7 @@ public class BTService extends Service {
|
||||||
int cmd = intent.getIntExtra( CMD_STR, -1 );
|
int cmd = intent.getIntExtra( CMD_STR, -1 );
|
||||||
DbgUtils.logf( "BTService.onStartCommand; cmd=%d", cmd );
|
DbgUtils.logf( "BTService.onStartCommand; cmd=%d", cmd );
|
||||||
if ( -1 == cmd ) {
|
if ( -1 == cmd ) {
|
||||||
} else if ( null == m_queue ) {
|
} else if ( null == m_sender ) {
|
||||||
DbgUtils.logf( "exiting: m_queue is null" );
|
DbgUtils.logf( "exiting: m_queue is null" );
|
||||||
stopSelf();
|
stopSelf();
|
||||||
} else {
|
} else {
|
||||||
|
@ -229,10 +228,10 @@ public class BTService extends Service {
|
||||||
case -1:
|
case -1:
|
||||||
break;
|
break;
|
||||||
case PING:
|
case PING:
|
||||||
m_queue.add( new BTQueueElem( BTCmd.PING ) );
|
m_sender.add( new BTQueueElem( BTCmd.PING ) );
|
||||||
break;
|
break;
|
||||||
case SCAN:
|
case SCAN:
|
||||||
m_queue.add( new BTQueueElem( BTCmd.SCAN ) );
|
m_sender.add( new BTQueueElem( BTCmd.SCAN ) );
|
||||||
break;
|
break;
|
||||||
case INVITE:
|
case INVITE:
|
||||||
int gameID = intent.getIntExtra( GAMEID_STR, -1 );
|
int gameID = intent.getIntExtra( GAMEID_STR, -1 );
|
||||||
|
@ -241,7 +240,7 @@ public class BTService extends Service {
|
||||||
int lang = intent.getIntExtra( LANG_STR, -1 );
|
int lang = intent.getIntExtra( LANG_STR, -1 );
|
||||||
int nPlayersT = intent.getIntExtra( NTO_STR, -1 );
|
int nPlayersT = intent.getIntExtra( NTO_STR, -1 );
|
||||||
int nPlayersH = intent.getIntExtra( NHE_STR, -1 );
|
int nPlayersH = intent.getIntExtra( NHE_STR, -1 );
|
||||||
m_queue.add( new BTQueueElem( BTCmd.INVITE, target, addr,
|
m_sender.add( new BTQueueElem( BTCmd.INVITE, target, addr,
|
||||||
gameID, lang,
|
gameID, lang,
|
||||||
nPlayersT, nPlayersH ) );
|
nPlayersT, nPlayersH ) );
|
||||||
break;
|
break;
|
||||||
|
@ -251,8 +250,7 @@ public class BTService extends Service {
|
||||||
addr = intent.getStringExtra( ADDR_STR );
|
addr = intent.getStringExtra( ADDR_STR );
|
||||||
gameID = intent.getIntExtra( GAMEID_STR, -1 );
|
gameID = intent.getIntExtra( GAMEID_STR, -1 );
|
||||||
if ( -1 != gameID ) {
|
if ( -1 != gameID ) {
|
||||||
Assert.assertNotNull( m_queue );
|
m_sender.add( new BTQueueElem( BTCmd.MESG_SEND, buf, target,
|
||||||
m_queue.add( new BTQueueElem( BTCmd.MESG_SEND, buf, target,
|
|
||||||
addr, gameID ) );
|
addr, gameID ) );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -281,28 +279,28 @@ public class BTService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BTListenerThread extends Thread {
|
private class BTListenerThread extends Thread {
|
||||||
|
private BluetoothServerSocket m_serverSocket;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
BluetoothServerSocket serverSocket;
|
|
||||||
while ( m_adapter.isEnabled() ) {
|
|
||||||
try {
|
try {
|
||||||
serverSocket = m_adapter.
|
m_serverSocket = m_adapter.
|
||||||
listenUsingRfcommWithServiceRecord( XWApp.getAppName(),
|
listenUsingRfcommWithServiceRecord( XWApp.getAppName(),
|
||||||
XWApp.getAppUUID() );
|
XWApp.getAppUUID() );
|
||||||
} catch ( java.io.IOException ioe ) {
|
} catch ( java.io.IOException ioe ) {
|
||||||
DbgUtils.logf( "listenUsingRfcommWithServiceRecord=>%s",
|
DbgUtils.logf( "listenUsingRfcommWithServiceRecord=>%s",
|
||||||
ioe.toString() );
|
ioe.toString() );
|
||||||
serverSocket = null;
|
m_serverSocket = null;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while ( null != m_serverSocket && m_adapter.isEnabled() ) {
|
||||||
|
|
||||||
BluetoothSocket socket = null;
|
BluetoothSocket socket = null;
|
||||||
DataInputStream inStream = null;
|
DataInputStream inStream = null;
|
||||||
int nRead = 0;
|
int nRead = 0;
|
||||||
try {
|
try {
|
||||||
DbgUtils.logf( "run: calling accept(60000)" );
|
DbgUtils.logf( "run: calling accept(60000)" );
|
||||||
socket = serverSocket.accept( 60000 ); // blocks
|
socket = m_serverSocket.accept( 60000 ); // blocks
|
||||||
addAddr( socket );
|
addAddr( socket );
|
||||||
DbgUtils.logf( "run: accept() returned" );
|
DbgUtils.logf( "run: accept() returned" );
|
||||||
inStream = new DataInputStream( socket.getInputStream() );
|
inStream = new DataInputStream( socket.getInputStream() );
|
||||||
|
@ -329,16 +327,27 @@ public class BTService extends Service {
|
||||||
DbgUtils.logf( "trying again..." );
|
DbgUtils.logf( "trying again..." );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( null != serverSocket ) {
|
if ( null != m_serverSocket ) {
|
||||||
try {
|
try {
|
||||||
serverSocket.close();
|
m_serverSocket.close();
|
||||||
} catch ( java.io.IOException ioe ) {
|
} catch ( java.io.IOException ioe ) {
|
||||||
DbgUtils.logf( "close()=>%s", ioe.toString() );
|
DbgUtils.logf( "close()=>%s", ioe.toString() );
|
||||||
}
|
}
|
||||||
serverSocket = null;
|
m_serverSocket = null;
|
||||||
}
|
}
|
||||||
|
} // run()
|
||||||
|
|
||||||
|
public void stopListening()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
m_serverSocket.close();
|
||||||
|
} catch ( java.io.IOException ioe ) {
|
||||||
|
DbgUtils.logf( "close()=>%s", ioe.toString() );
|
||||||
}
|
}
|
||||||
|
m_serverSocket = null;
|
||||||
|
interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,27 +356,28 @@ public class BTService extends Service {
|
||||||
Set<BluetoothDevice> pairedDevs = m_adapter.getBondedDevices();
|
Set<BluetoothDevice> pairedDevs = m_adapter.getBondedDevices();
|
||||||
DbgUtils.logf( "ping: got %d paired devices", pairedDevs.size() );
|
DbgUtils.logf( "ping: got %d paired devices", pairedDevs.size() );
|
||||||
for ( BluetoothDevice dev : pairedDevs ) {
|
for ( BluetoothDevice dev : pairedDevs ) {
|
||||||
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
DbgUtils.logf( "PingThread: got socket to device %s",
|
DbgUtils.logf( "PingThread: got socket to device %s",
|
||||||
dev.getName() );
|
dev.getName() );
|
||||||
BluetoothSocket socket =
|
BluetoothSocket socket =
|
||||||
dev.createRfcommSocketToServiceRecord( XWApp.getAppUUID() );
|
dev.createRfcommSocketToServiceRecord( XWApp.getAppUUID() );
|
||||||
if ( null != socket ) {
|
if ( null != socket ) {
|
||||||
socket.connect();
|
DataOutputStream os = connect( socket, BTCmd.PING );
|
||||||
|
if ( null != os ) {
|
||||||
DbgUtils.logf( "sendPings: connected" );
|
|
||||||
DataOutputStream os =
|
|
||||||
new DataOutputStream( socket.getOutputStream() );
|
|
||||||
os.writeByte( BTCmd.PING.ordinal() );
|
|
||||||
DbgUtils.logf( "sendPings: wrote" );
|
|
||||||
os.flush();
|
os.flush();
|
||||||
Thread killer = killSocketIn( socket, 10 );
|
Thread killer = killSocketIn( socket, 10 );
|
||||||
|
|
||||||
DataInputStream is =
|
DataInputStream is =
|
||||||
new DataInputStream( socket.getInputStream() );
|
new DataInputStream( socket.getInputStream() );
|
||||||
boolean success = BTCmd.PONG == BTCmd.values()[is.readByte()];
|
success = BTCmd.PONG == BTCmd.values()[is.readByte()];
|
||||||
killer.interrupt();
|
killer.interrupt();
|
||||||
|
}
|
||||||
socket.close();
|
socket.close();
|
||||||
|
}
|
||||||
|
} catch ( java.io.IOException ioe ) {
|
||||||
|
DbgUtils.logf( "sendPings: ioe: %s", ioe.toString() );
|
||||||
|
}
|
||||||
|
|
||||||
if ( success ) {
|
if ( success ) {
|
||||||
DbgUtils.logf( "got PONG from %s", dev.getName() );
|
DbgUtils.logf( "got PONG from %s", dev.getName() );
|
||||||
|
@ -377,10 +387,6 @@ public class BTService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch ( java.io.IOException ioe ) {
|
|
||||||
DbgUtils.logf( "sendPings: ioe: %s", ioe.toString() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendInvite( BTQueueElem elem )
|
private void sendInvite( BTQueueElem elem )
|
||||||
|
@ -391,10 +397,9 @@ public class BTService extends Service {
|
||||||
BluetoothSocket socket =
|
BluetoothSocket socket =
|
||||||
dev.createRfcommSocketToServiceRecord( XWApp.getAppUUID() );
|
dev.createRfcommSocketToServiceRecord( XWApp.getAppUUID() );
|
||||||
if ( null != socket ) {
|
if ( null != socket ) {
|
||||||
socket.connect();
|
boolean success = false;
|
||||||
DataOutputStream outStream =
|
DataOutputStream outStream = connect( socket, BTCmd.INVITE );
|
||||||
new DataOutputStream( socket.getOutputStream() );
|
if ( null != outStream ) {
|
||||||
outStream.writeByte( BTCmd.INVITE.ordinal() );
|
|
||||||
outStream.writeInt( elem.m_gameID );
|
outStream.writeInt( elem.m_gameID );
|
||||||
outStream.writeInt( elem.m_lang );
|
outStream.writeInt( elem.m_lang );
|
||||||
outStream.writeInt( elem.m_nPlayersT );
|
outStream.writeInt( elem.m_nPlayersT );
|
||||||
|
@ -403,10 +408,11 @@ public class BTService extends Service {
|
||||||
|
|
||||||
DataInputStream inStream =
|
DataInputStream inStream =
|
||||||
new DataInputStream( socket.getInputStream() );
|
new DataInputStream( socket.getInputStream() );
|
||||||
boolean success =
|
success = BTCmd.INVITE_ACCPT
|
||||||
BTCmd.INVITE_ACCPT == BTCmd.values()[inStream.readByte()];
|
== BTCmd.values()[inStream.readByte()];
|
||||||
DbgUtils.logf( "sendInvite(): invite done: success=%b",
|
DbgUtils.logf( "sendInvite(): invite done: success=%b",
|
||||||
success );
|
success );
|
||||||
|
}
|
||||||
socket.close();
|
socket.close();
|
||||||
|
|
||||||
BTEvent evt = success ? BTEvent.NEWGAME_SUCCESS
|
BTEvent evt = success ? BTEvent.NEWGAME_SUCCESS
|
||||||
|
@ -426,10 +432,8 @@ public class BTService extends Service {
|
||||||
BluetoothSocket socket =
|
BluetoothSocket socket =
|
||||||
dev.createRfcommSocketToServiceRecord( XWApp.getAppUUID() );
|
dev.createRfcommSocketToServiceRecord( XWApp.getAppUUID() );
|
||||||
if ( null != socket ) {
|
if ( null != socket ) {
|
||||||
socket.connect();
|
DataOutputStream outStream = connect( socket, BTCmd.MESG_SEND );
|
||||||
DataOutputStream outStream =
|
if ( null != outStream ) {
|
||||||
new DataOutputStream( socket.getOutputStream() );
|
|
||||||
outStream.writeByte( BTCmd.MESG_SEND.ordinal() );
|
|
||||||
outStream.writeInt( elem.m_gameID );
|
outStream.writeInt( elem.m_gameID );
|
||||||
|
|
||||||
short len = (short)elem.m_msg.length;
|
short len = (short)elem.m_msg.length;
|
||||||
|
@ -444,6 +448,7 @@ public class BTService extends Service {
|
||||||
success =
|
success =
|
||||||
BTCmd.MESG_ACCPT == BTCmd.values()[inStream.readByte()];
|
BTCmd.MESG_ACCPT == BTCmd.values()[inStream.readByte()];
|
||||||
killer.interrupt();
|
killer.interrupt();
|
||||||
|
}
|
||||||
socket.close();
|
socket.close();
|
||||||
}
|
}
|
||||||
} catch ( java.io.IOException ioe ) {
|
} catch ( java.io.IOException ioe ) {
|
||||||
|
@ -497,6 +502,18 @@ public class BTService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BTSenderThread extends Thread {
|
private class BTSenderThread extends Thread {
|
||||||
|
private LinkedBlockingQueue<BTQueueElem> m_queue;
|
||||||
|
|
||||||
|
public BTSenderThread( LinkedBlockingQueue<BTQueueElem> queue )
|
||||||
|
{
|
||||||
|
m_queue = queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add( BTQueueElem elem )
|
||||||
|
{
|
||||||
|
m_queue.add( elem );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
|
@ -661,15 +678,16 @@ public class BTService extends Service {
|
||||||
|
|
||||||
private void startSender()
|
private void startSender()
|
||||||
{
|
{
|
||||||
m_queue = new LinkedBlockingQueue<BTQueueElem>();
|
LinkedBlockingQueue<BTQueueElem> queue =
|
||||||
m_sender = new BTSenderThread();
|
new LinkedBlockingQueue<BTQueueElem>();
|
||||||
|
m_sender = new BTSenderThread( queue );
|
||||||
m_sender.start();
|
m_sender.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopListener()
|
private void stopListener()
|
||||||
{
|
{
|
||||||
DbgUtils.logf( "stopListener..." );
|
DbgUtils.logf( "stopListener..." );
|
||||||
m_listener.interrupt();
|
m_listener.stopListening();
|
||||||
try {
|
try {
|
||||||
m_listener.join( 100 );
|
m_listener.join( 100 );
|
||||||
} catch ( InterruptedException ie ) {
|
} catch ( InterruptedException ie ) {
|
||||||
|
@ -692,6 +710,26 @@ public class BTService extends Service {
|
||||||
DbgUtils.logf( "stopSender done" );
|
DbgUtils.logf( "stopSender done" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DataOutputStream connect( BluetoothSocket socket, BTCmd cmd )
|
||||||
|
{
|
||||||
|
DbgUtils.logf( "connecting to %s to send %s",
|
||||||
|
socket.getRemoteDevice().getName(), cmd.toString() );
|
||||||
|
// Docs say always call cancelDiscovery before trying to connect
|
||||||
|
m_adapter.cancelDiscovery();
|
||||||
|
|
||||||
|
DataOutputStream dos;
|
||||||
|
try {
|
||||||
|
socket.connect();
|
||||||
|
dos = new DataOutputStream( socket.getOutputStream() );
|
||||||
|
dos.writeByte( cmd.ordinal() );
|
||||||
|
DbgUtils.logf( "connect successful" );
|
||||||
|
} catch ( java.io.IOException ioe ) {
|
||||||
|
DbgUtils.logf( "connect()=>%s", ioe.toString() );
|
||||||
|
dos = null;
|
||||||
|
}
|
||||||
|
return dos;
|
||||||
|
}
|
||||||
|
|
||||||
private Thread killSocketIn( final BluetoothSocket socket, int seconds )
|
private Thread killSocketIn( final BluetoothSocket socket, int seconds )
|
||||||
{
|
{
|
||||||
final int millis = seconds * 1000;
|
final int millis = seconds * 1000;
|
||||||
|
@ -721,8 +759,7 @@ public class BTService extends Service {
|
||||||
public int transportSend( byte[] buf, final CommsAddrRec addr, int gameID )
|
public int transportSend( byte[] buf, final CommsAddrRec addr, int gameID )
|
||||||
{
|
{
|
||||||
Assert.assertNotNull( addr );
|
Assert.assertNotNull( addr );
|
||||||
Assert.assertNotNull( m_queue );
|
m_sender.add( new BTQueueElem( BTCmd.MESG_SEND, buf,
|
||||||
m_queue.add( new BTQueueElem( BTCmd.MESG_SEND, buf,
|
|
||||||
addr.bt_hostName, addr.bt_btAddr,
|
addr.bt_hostName, addr.bt_btAddr,
|
||||||
gameID ) );
|
gameID ) );
|
||||||
return buf.length;
|
return buf.length;
|
||||||
|
|
Loading…
Reference in a new issue