package andraus.bluetoothhidemu.sock;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import andraus.bluetoothhidemu.BluetoothHidEmuActivity;
import andraus.bluetoothhidemu.util.DoLog;
import android.bluetooth.BluetoothSocket;
public class BluetoothSocketThread extends Thread {
private String TAG = BluetoothHidEmuActivity.TAG + "Comm";
private static final int BUF_SIZE = 16;
BluetoothSocket mSocket = null;
static final int STATE_NONE = 0;
static final int STATE_WAITING = 1;
static final int STATE_ACCEPTED = 2;
static final int STATE_DROPPING = 3;
static final int STATE_DROPPED = 4;
static final int TIME_5_SEC = 5000;
static final int TIME_1_SEC = 1000;
private int mState = 0;
private int mSuggestedRetryTimeMs = 0;
private InputStream mInputStream = null;
private OutputStream mOutputStream = null;
public BluetoothSocketThread(String name) {
super();
if (name == null) {
throw new IllegalStateException("name is null");
}
setName(name);
}
public BluetoothSocketThread(BluetoothSocket socket, String name) {
super(name);
if (socket == null) {
throw new IllegalStateException("socket is null");
}
mSocket = socket;
}
@Override
public void run() {
try {
mState = STATE_WAITING;
mSocket.connect();
} catch (IOException e) {
DoLog.e(TAG, getName(), e);
dropConnection(TIME_5_SEC);
}
if (mSocket != null && mState == STATE_WAITING) {
try {
mState = STATE_ACCEPTED;
mInputStream = mSocket.getInputStream();
mOutputStream = mSocket.getOutputStream();
int numBytes = 0;
byte[] bytes = new byte[BUF_SIZE];
while (mState == STATE_ACCEPTED) {
if (mInputStream.available() > 0 && (numBytes = mInputStream.read(bytes)) >= 0) {
String s = getByteString(bytes, numBytes);
DoLog.d(TAG, getName() + " - received: " + s);
DoLog.d(TAG, getName() + " - size: " + numBytes);
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
DoLog.e(TAG, getName(), e);
dropConnection(TIME_5_SEC);
}
}
} catch (IOException e) {
DoLog.e(TAG, getName(), e);
dropConnection(TIME_5_SEC);
}
}
mState = STATE_DROPPED;
}
public synchronized void sendBytes(byte[] bytes) {
if (mState == STATE_ACCEPTED) {
try {
DoLog.d(TAG, "Sending bytes to " + getName() + ": " + getByteString(bytes, bytes.length));
mOutputStream.write(bytes);
mOutputStream.flush();
} catch (IOException e) {
// connection dropped for some reason.
DoLog.e(TAG, getName(),e);
dropConnection(TIME_1_SEC);
}
}
}
private synchronized void dropConnection(int suggestedRetryTimeMs) {
DoLog.d(TAG, "dropping socket - " + mSocket);
mState = STATE_DROPPING;
mSuggestedRetryTimeMs = suggestedRetryTimeMs;
if (mSocket != null) {
try {
if (mInputStream != null) mInputStream.close();
if (mOutputStream != null) mOutputStream.close();
mSocket.close();
} catch (IOException e) {
DoLog.w(TAG, getName(), e);
}
}
mState = STATE_DROPPED;
}
public synchronized void stopGracefully() {
if (mState == STATE_ACCEPTED || mState == STATE_WAITING) {
dropConnection(TIME_5_SEC);
}
mState = STATE_NONE;
}
public int getConnectionState() {
//DoLog.d(TAG,getName() + " state - " + mState);
return mState;
}
public int getSuggestedRetryTimeMs() {
return mSuggestedRetryTimeMs;
}
public void setSocket(BluetoothSocket socket) {
mSocket = socket;
}
private String getByteString(byte[] bytes, int size) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < size; i++) {
s.append(String.format("0x%02x ", bytes[i]));
}
return s.toString();
}
}