blob: 18ca8588a2bb8a2bcb8e1dd9902419455e136413 [file] [log] [blame]
/*
* Copyright 2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.android_scripting.facade.bluetooth;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.facade.EventFacade;
import com.googlecode.android_scripting.facade.FacadeManager;
import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcDefault;
import com.googlecode.android_scripting.rpc.RpcOptional;
import com.googlecode.android_scripting.rpc.RpcParameter;
import org.apache.commons.codec.binary.Base64Codec;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* Bluetooth functions.
*
*/
public class BluetoothSocketConnFacade extends RpcReceiver {
private final Service mService;
private final BluetoothAdapter mBluetoothAdapter;
private Map<String, BluetoothConnection> mConnections =
new HashMap<String, BluetoothConnection>();
private final EventFacade mEventFacade;
private ConnectThread mConnectThread;
private AcceptThread mAcceptThread;
private byte mTxPktIndex = 0;
private static final String DEFAULT_PSM = "161"; //=0x00A1
// UUID for SL4A.
protected static final String DEFAULT_UUID = "457807c0-4897-11df-9879-0800200c9a66";
protected static final String SDP_NAME = "SL4A";
protected static final String DEFAULT_LE_DATA_LENGTH = "23";
public BluetoothSocketConnFacade(FacadeManager manager) {
super(manager);
mEventFacade = manager.getReceiver(EventFacade.class);
mService = manager.getService();
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
private BluetoothConnection getConnection(String connID) throws IOException {
if (connID == null) {
throw new IOException("Connection ID is null");
}
Log.d("BluetoothConnection:getConnection: connID=" + connID);
BluetoothConnection conn = null;
if (connID.trim().length() > 0) {
conn = mConnections.get(connID);
} else if (mConnections.size() == 1) {
conn = (BluetoothConnection) mConnections.values().toArray()[0];
} else {
Log.e("More than one available connections. Num=" + mConnections.size());
throw new IOException("More than 1 available connections. Num=" + mConnections.size());
}
if (conn == null) {
throw new IOException("Bluetooth connection not established. connID=" + connID);
}
return conn;
}
private String addConnection(BluetoothConnection conn) {
String uuid = UUID.randomUUID().toString();
mConnections.put(uuid, conn);
conn.setUUID(uuid);
return uuid;
}
/**
* Create L2CAP socket to Bluetooth device
*
* @param address the bluetooth address to open the socket on
* @param channel the channel to open the socket on
* @throws Exception
*/
@Rpc(description = "Create L2CAP socket to Bluetooth deice")
public void bluetoothSocketConnCreateL2capSocket(@RpcParameter(name = "address") String address,
@RpcParameter(name = "channel") Integer channel) throws Exception {
BluetoothDevice mDevice;
mDevice = mBluetoothAdapter.getRemoteDevice(address);
Class bluetoothDeviceClass = Class.forName("android.bluetooth.BluetoothDevice");
Method createL2capSocketMethod =
bluetoothDeviceClass.getMethod("createL2capSocket", int.class);
createL2capSocketMethod.invoke(mDevice, channel);
}
/**
* Begin Connect Thread using UUID
*
* @param address the mac address of the device to connect to
* @param uuid the UUID that is used by the server device
* @throws Exception
*/
@Rpc(description = "Begins a thread initiate an L2CAP socket connection over Bluetooth. ")
public void bluetoothSocketConnBeginConnectThreadUuid(
@RpcParameter(name = "address",
description = "The mac address of the device to connect to.") String address,
@RpcParameter(name = "uuid",
description = "The UUID passed here must match the UUID used by the server device.")
@RpcDefault(DEFAULT_UUID) String uuid)
throws IOException {
BluetoothDevice mDevice;
mDevice = mBluetoothAdapter.getRemoteDevice(address);
ConnectThread connectThread = new ConnectThread(mDevice, uuid);
connectThread.start();
mConnectThread = connectThread;
}
/**
* Begin Connect Thread using PSM value
*
* @param address the mac address of the device to connect to
* @param isBle the transport is LE
* @param psmValue the assigned PSM value to use for this socket connection
* @throws Exception
*/
@Rpc(description = "Begins a thread initiate an L2CAP CoC connection over Bluetooth. ")
public void bluetoothSocketConnBeginConnectThreadPsm(
@RpcParameter(name = "address",
description = "The mac address of the device to connect to.") String address,
@RpcParameter(name = "isBle", description = "Is transport BLE?") @RpcDefault("false")
Boolean isBle,
@RpcParameter(name = "psmValue") @RpcDefault(DEFAULT_PSM) Integer psmValue,
@RpcParameter(name = "securedConn") @RpcDefault("false") Boolean securedConn)
throws IOException {
BluetoothDevice mDevice;
mDevice = mBluetoothAdapter.getRemoteDevice(address);
Log.d("bluetoothSocketConnBeginConnectThreadPsm: Coc connecting to " + address + ", isBle="
+ isBle + ", psmValue=" + psmValue + ", securedConn=" + securedConn);
ConnectThread connectThread = new ConnectThread(mDevice, psmValue, isBle, securedConn);
connectThread.start();
mConnectThread = connectThread;
}
/**
* Get last connection ID
*
* @return String the last connection ID
* @throws Exception
*/
@Rpc(description = "Returns the connection ID of the last connection.")
public String bluetoothGetLastConnId()
throws IOException {
if (mAcceptThread != null) {
String connUuid = mAcceptThread.getConnUuid();
Log.d("bluetoothGetLastConnId from Accept Thread: connUuid=" + connUuid);
return connUuid;
}
if (mConnectThread != null) {
String connUuid = mConnectThread.getConnUuid();
Log.d("bluetoothGetLastConnId from Connect Thread: connUuid=" + connUuid);
return connUuid;
}
Log.e("bluetoothGetLastConnId: No active threads");
return null;
}
/**
* Kill the connect thread
*/
@Rpc(description = "Kill thread")
public void bluetoothSocketConnKillConnThread() {
try {
mConnectThread.cancel();
mConnectThread.join(5000);
} catch (InterruptedException e) {
Log.e("Interrupted Exception: " + e.toString());
}
}
/**
* Closes an active Client socket
*
* @throws Exception
*/
@Rpc(description = "Close an active Client socket")
public void bluetoothSocketConnEndConnectThread() throws IOException {
mConnectThread.cancel();
}
/**
* Closes an active Server socket
*
* @throws Exception
*/
@Rpc(description = "Close an active Server socket")
public void bluetoothSocketConnEndAcceptThread() throws IOException {
mAcceptThread.cancel();
}
/**
* Returns active Bluetooth mConnections
*
* @return map of active connections and its remote addresses
*/
@Rpc(description = "Returns active Bluetooth mConnections.")
public Map<String, String> bluetoothSocketConnActiveConnections() {
Map<String, String> out = new HashMap<String, String>();
for (Map.Entry<String, BluetoothConnection> entry : mConnections.entrySet()) {
if (entry.getValue().isConnected()) {
out.put(entry.getKey(), entry.getValue().getRemoteBluetoothAddress());
}
}
return out;
}
/**
* Returns the name of the connected device
*
* @return string name of connected device
* @throws Exception
*/
@Rpc(description = "Returns the name of the connected device.")
public String bluetoothSocketConnGetConnectedDeviceName(
@RpcParameter(name = "connID", description = "Connection id") @RpcOptional
@RpcDefault("") String connID)
throws IOException {
BluetoothConnection conn = getConnection(connID);
return conn.getConnectedDeviceName();
}
/**
* Begins a thread to accept an L2CAP connection over Bluetooth with UUID
*
* @param uuid the UUID to identify this L2CAP connection
* @param timeout the time to wait for new connection
* @throws Exception
*/
@Rpc(description = "Begins a thread to accept an L2CAP connection over Bluetooth. ")
public void bluetoothSocketConnBeginAcceptThreadUuid(
@RpcParameter(name = "uuid") @RpcDefault(DEFAULT_UUID) String uuid,
@RpcParameter(name = "timeout",
description = "How long to wait for a new connection, 0 is wait for ever")
@RpcDefault("0") Integer timeout)
throws IOException {
Log.d("bluetoothSocketConnBeginAcceptThreadUuid: uuid=" + uuid);
AcceptThread acceptThread = new AcceptThread(uuid, timeout.intValue());
acceptThread.start();
mAcceptThread = acceptThread;
}
/**
* Begins a thread to accept an L2CAP connection over Bluetooth with PSM value
*
* @param psmValue the PSM value to identify this L2CAP connection
* @param timeout the time to wait for new connection
* @param isBle whether this connection uses LE transport
* @throws Exception
*/
@Rpc(description = "Begins a thread to accept an Coc connection over Bluetooth. ")
public void bluetoothSocketConnBeginAcceptThreadPsm(
@RpcParameter(name = "timeout",
description = "How long to wait for a new connection, 0 is wait for ever")
@RpcDefault("0") Integer timeout,
@RpcParameter(name = "isBle",
description = "Is transport BLE?")
@RpcDefault("false") Boolean isBle,
@RpcParameter(name = "securedConn",
description = "Using secured connection?")
@RpcDefault("false") Boolean securedConn,
@RpcParameter(name = "psmValue") @RpcDefault(DEFAULT_PSM) Integer psmValue)
throws IOException {
Log.d("bluetoothSocketConnBeginAcceptThreadPsm: PSM value=" + psmValue);
AcceptThread acceptThread = new AcceptThread(psmValue.intValue(), timeout.intValue(),
isBle, securedConn);
acceptThread.start();
mAcceptThread = acceptThread;
}
/**
* Get the current BluetoothServerSocket PSM value
* @return Integer the assigned PSM value
* @throws Exception
*/
@Rpc(description = "Returns the PSM value")
public Integer bluetoothSocketConnGetPsm() throws IOException {
Integer psm = new Integer(mAcceptThread.getPsm());
Log.d("bluetoothSocketConnGetPsm: PSM value=" + psm);
return psm;
}
/**
* Set the current BluetoothSocket LE Data Length value to the maximum supported by this BT
* controller. This command suggests to the BT controller to set its maximum transmission packet
* size.
* @throws Exception
*/
@Rpc(description = "Request Maximum Tx Data Length")
public void bluetoothSocketRequestMaximumTxDataLength()
throws IOException {
Log.d("bluetoothSocketRequestMaximumTxDataLength");
if (mConnectThread == null) {
String connUuid = mConnectThread.getConnUuid();
throw new IOException("bluetoothSocketRequestMaximumTxDataLength: no active connect"
+ " thread");
}
BluetoothSocket socket = mConnectThread.getSocket();
if (socket == null) {
throw new IOException("bluetoothSocketRequestMaximumTxDataLength: no active connect"
+ " socket");
}
socket.requestMaximumTxDataLength();
}
/**
* Sends ASCII characters over the currently open Bluetooth connection
*
* @param ascii the string to write
* @param connID the connection ID
* @throws Exception
*/
@Rpc(description = "Sends ASCII characters over the currently open Bluetooth connection.")
public void bluetoothSocketConnWrite(@RpcParameter(name = "ascii") String ascii,
@RpcParameter(name = "connID", description = "Connection id")
@RpcDefault("") String connID)
throws IOException {
BluetoothConnection conn = getConnection(connID);
try {
conn.write(ascii);
} catch (IOException e) {
mConnections.remove(conn.getUUID());
throw e;
}
}
/**
* Read up to bufferSize ASCII characters
*
* @param bufferSize the size of buffer to read
* @param connID the connection ID
* @return the string buffer containing the read ASCII characters
* @throws Exception
*/
@Rpc(description = "Read up to bufferSize ASCII characters.")
public String bluetoothSocketConnRead(
@RpcParameter(name = "bufferSize") @RpcDefault("4096") Integer bufferSize,
@RpcParameter(name = "connID", description = "Connection id") @RpcOptional
@RpcDefault("") String connID)
throws IOException {
BluetoothConnection conn = getConnection(connID);
try {
return conn.read(bufferSize);
} catch (IOException e) {
mConnections.remove(conn.getUUID());
throw e;
}
}
/**
* Send bytes over the currently open Bluetooth connection
*
* @param base64 the based64-encoded string to write
* @param connID the connection ID
* @throws Exception
*/
@Rpc(description = "Send bytes over the currently open Bluetooth connection.")
public void bluetoothSocketConnWriteBinary(
@RpcParameter(name = "base64",
description = "A base64 encoded String of the bytes to be sent.") String base64,
@RpcParameter(name = "connID",
description = "Connection id") @RpcDefault("") @RpcOptional String connID)
throws IOException {
BluetoothConnection conn = getConnection(connID);
try {
conn.write(Base64Codec.decodeBase64(base64));
} catch (IOException e) {
mConnections.remove(conn.getUUID());
throw e;
}
}
/**
* Read up to bufferSize bytes and return a chunked, base64 encoded string
*
* @param bufferSize the size of buffer to read
* @param connID the connection ID
* @return the string buffer containing the read base64-encoded characters
* @throws Exception
*/
@Rpc(description = "Read up to bufferSize bytes and return a chunked, base64 encoded string.")
public String bluetoothSocketConnReadBinary(
@RpcParameter(name = "bufferSize") @RpcDefault("4096") Integer bufferSize,
@RpcParameter(name = "connID", description = "Connection id") @RpcDefault("")
@RpcOptional String connID)
throws IOException {
BluetoothConnection conn = getConnection(connID);
try {
return Base64Codec.encodeBase64String(conn.readBinary(bufferSize));
} catch (IOException e) {
mConnections.remove(conn.getUUID());
throw e;
}
}
/**
* Returns true if the next read is guaranteed not to block
*
* @param connID the connection ID
* @return true if the the next read is guaranteed not to block
* @throws Exception
*/
@Rpc(description = "Returns True if the next read is guaranteed not to block.")
public Boolean bluetoothSocketConnReadReady(
@RpcParameter(name = "connID", description = "Connection id") @RpcDefault("")
@RpcOptional String connID)
throws IOException {
BluetoothConnection conn = getConnection(connID);
try {
return conn.readReady();
} catch (IOException e) {
mConnections.remove(conn.getUUID());
throw e;
}
}
/**
* Read the next line
*
* @param connID the connection ID
* @return the string buffer containing the read line
* @throws Exception
*/
@Rpc(description = "Read the next line.")
public String bluetoothSocketConnReadLine(
@RpcParameter(name = "connID", description = "Connection id") @RpcOptional
@RpcDefault("") String connID)
throws IOException {
BluetoothConnection conn = getConnection(connID);
try {
return conn.readLine();
} catch (IOException e) {
mConnections.remove(conn.getUUID());
throw e;
}
}
private static byte getNextOutputChar(byte in) {
in++;
if (in >= 'z') {
in = 'a';
}
return in;
}
private static int getNextOutputChar(int in) {
in++;
if (in >= 'z') {
in = 'a';
}
return in;
}
/**
* Send a data buffer with auto-generated data
*
* @param numBuffers the number of buffers to send
* @param bufferSize the buffer size in bytes
* @param connID the connection ID
* @throws Exception
*/
@Rpc(description = "Send a large buffer of bytes for throughput test")
public void bluetoothConnectionThroughputSend(
@RpcParameter(name = "numBuffers", description = "number of buffers")
Integer numBuffers,
@RpcParameter(name = "bufferSize", description = "buffer size") Integer bufferSize,
@RpcParameter(name = "connID", description = "Connection id")
@RpcDefault("") @RpcOptional String connID)
throws IOException {
Log.d("bluetoothConnectionThroughputSend: numBuffers=" + numBuffers + ", bufferSize="
+ bufferSize + ", connID=" + connID + ", mTxPktIndex=" + mTxPktIndex);
// Generate a buffer of given size
byte[] outBuf = new byte[bufferSize];
byte outChar = 'a';
// The first byte is the buffer index
int i = 0;
outBuf[i++] = mTxPktIndex;
for (; i < bufferSize; i++) {
outBuf[i] = outChar;
outChar = getNextOutputChar(outChar);
}
BluetoothConnection conn = getConnection(connID);
try {
for (i = 0; i < numBuffers; i++) {
Log.d("bluetoothConnectionThroughputSend: sending " + i + " buffer.");
outBuf[0] = mTxPktIndex++;
conn.write(outBuf);
}
} catch (IOException e) {
mConnections.remove(conn.getUUID());
throw e;
}
}
/**
* Read a number of data buffers and make sure the data is correct
*
* @param numBuffers the number of buffers to send
* @param bufferSize the buffer size in bytes
* @param connID the connection ID
* @return the data rate read in terms of bytes per second
* @throws Exception
*/
@Rpc(description = "Returns the throughput in bytes-per-sec, or Returns 0 if unsuccessful")
public Integer bluetoothConnectionThroughputRead(
@RpcParameter(name = "numBuffers", description = "number of buffers")
Integer numBuffers,
@RpcParameter(name = "bufferSize", description = "buffer size") Integer bufferSize,
@RpcParameter(name = "connID", description = "Connection id")
@RpcDefault("") @RpcOptional String connID)
throws IOException {
Log.d("bluetoothConnectionThroughputRead: numBuffers=" + numBuffers + ", bufferSize="
+ bufferSize);
BluetoothConnection conn = getConnection(connID);
long startTesttime = System.currentTimeMillis();
byte bufIndex = (byte) 0x00FF;
try {
ByteArrayOutputStream tmp_array = new ByteArrayOutputStream();
for (int i = 0; i < numBuffers; i++) {
// Read one buffer
while (tmp_array.size() < bufferSize) {
byte[] tmp_read = conn.readBinary(bufferSize);
if (tmp_read.length == 0) {
break;
}
tmp_array.write(tmp_read);
}
byte[] readBuf = tmp_array.toByteArray();
tmp_array.reset();
// Make sure the contents are valid
int nextInChar = 'a';
int j = 0;
// The first byte is the buffer index
if (i == 0) {
bufIndex = readBuf[j];
} else {
bufIndex++;
if (bufIndex != readBuf[j]) {
Log.e("bluetoothConnectionThroughputRead: Wrong Buffer index (First byte). "
+ "Expected=" + bufIndex + ", read=" + readBuf[j]);
throw new IOException("bluetoothConnectionThroughputRead: Wrong Buffer("
+ (i + 1) + ") index (First byte). Expected="
+ bufIndex + ", read=" + readBuf[j]);
}
}
Log.d("bluetoothConnectionThroughputRead: First byte=" + bufIndex);
j++;
for (; j < bufferSize; j++) {
if (readBuf[j] != nextInChar) {
Log.e("Last Read Char Read wrong value. Read=" + String.valueOf(readBuf[j])
+ ", Expected=" + String.valueOf(nextInChar));
throw new IOException("Read mismatched at buf=" + i + ", idx=" + j);
}
nextInChar = getNextOutputChar(nextInChar);
}
Log.d("bluetoothConnectionThroughputRead: Buffer Read index=" + i);
if (bufferSize < readBuf.length) {
tmp_array.write(readBuf, bufferSize, readBuf.length - bufferSize);
}
}
long endTesttime = System.currentTimeMillis();
long diffTime = endTesttime - startTesttime; // time delta in milliseconds
Log.d("bluetoothConnectionThroughputRead: Completed! numBuffers=" + numBuffers
+ ",delta time=" + diffTime + " millisec");
long numBytes = numBuffers * bufferSize;
long dataRatePerMsec;
if (diffTime > 0) {
dataRatePerMsec = (1000L * numBytes) / diffTime;
} else {
dataRatePerMsec = 9999;
}
Integer dataRate = new Integer((int) dataRatePerMsec);
Log.d("bluetoothConnectionThroughputRead: Completed! numBytes=" + numBytes
+ ", data rate=" + dataRate + " bytes per sec");
return dataRate;
} catch (IOException e) {
mConnections.remove(conn.getUUID());
throw e;
}
}
/**
* Stops Bluetooth connection
*
* @param connID the connection ID
*/
@Rpc(description = "Stops Bluetooth connection.")
public void bluetoothSocketConnStop(
@RpcParameter(name = "connID", description = "Connection id") @RpcOptional
@RpcDefault("") String connID) {
BluetoothConnection conn;
try {
conn = getConnection(connID);
} catch (IOException e) {
e.printStackTrace();
return;
}
if (conn == null) {
Log.d("bluetoothSocketConnStop: conn is NULL. connID=%s" + connID);
return;
}
Log.d("bluetoothSocketConnStop: connID=" + connID + ", UUID=" + conn.getUUID());
conn.stop();
mConnections.remove(conn.getUUID());
if (mAcceptThread != null) {
mAcceptThread.cancel();
}
if (mConnectThread != null) {
mConnectThread.cancel();
}
}
@Override
public void shutdown() {
for (Map.Entry<String, BluetoothConnection> entry : mConnections.entrySet()) {
entry.getValue().stop();
}
mConnections.clear();
if (mAcceptThread != null) {
mAcceptThread.cancel();
}
if (mConnectThread != null) {
mConnectThread.cancel();
}
}
private class ConnectThread extends Thread {
private final BluetoothSocket mSocket;
private final Boolean mIsBle;
String mConnUuid;
ConnectThread(BluetoothDevice device, String uuid) {
BluetoothSocket tmp = null;
try {
tmp = device.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
} catch (IOException createSocketException) {
Log.e("Failed to create socket: " + createSocketException.toString());
}
mIsBle = false;
mSocket = tmp;
}
ConnectThread(BluetoothDevice device,
@RpcParameter(name = "psmValue")
@RpcDefault(DEFAULT_PSM) Integer psmValue,
@RpcParameter(name = "isBle") @RpcDefault("false") boolean isBle,
@RpcParameter(name = "securedConn")
@RpcDefault("false") boolean securedConn) {
BluetoothSocket tmp = null;
Log.d("ConnectThread: psmValue=" + psmValue + ", isBle=" + isBle
+ ", securedConn=" + securedConn);
try {
if (isBle) {
if (securedConn) {
tmp = device.createL2capChannel(psmValue);
} else {
tmp = device.createInsecureL2capChannel(psmValue);
}
} else {
if (securedConn) {
tmp = device.createL2capSocket(psmValue);
} else {
tmp = device.createInsecureL2capSocket(psmValue);
}
}
// Secured version: tmp = device.createL2capSocket(0x1011);
// tmp = device.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
} catch (IOException createSocketException) {
Log.e("Failed to create socket: " + createSocketException.toString());
}
mIsBle = isBle;
mSocket = tmp;
}
public void run() {
mBluetoothAdapter.cancelDiscovery();
try {
BluetoothConnection conn;
mSocket.connect();
conn = new BluetoothConnection(mSocket);
mConnUuid = addConnection(conn);
Log.d("ConnectThread:run: isConnected=" + mSocket.isConnected() + ", address="
+ mSocket.getRemoteDevice().getAddress() + ", uuid=" + mConnUuid);
} catch (IOException connectException) {
Log.e("ConnectThread::run(): Error: Connection Unsuccessful");
cancel();
return;
}
}
public void cancel() {
if (mSocket != null) {
try {
mSocket.close();
} catch (IOException closeException) {
Log.e("Failed to close socket: " + closeException.toString());
}
}
}
public BluetoothSocket getSocket() {
return mSocket;
}
public String getConnUuid() {
Log.d("ConnectThread::getConnUuid(): mConnUuid=" + mConnUuid);
return mConnUuid;
}
}
private class AcceptThread extends Thread {
private final BluetoothServerSocket mServerSocket;
private final int mTimeout;
private BluetoothSocket mSocket;
String mConnUuid;
AcceptThread(String uuid, int timeout) {
BluetoothServerSocket tmp = null;
mTimeout = timeout;
try {
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(SDP_NAME,
UUID.fromString(uuid));
} catch (IOException createSocketException) {
Log.e("Failed to create socket: " + createSocketException.toString());
}
mServerSocket = tmp;
Log.d("AcceptThread: uuid=" + uuid);
}
AcceptThread(int psmValue, int timeout, boolean isBle, boolean securedConn) {
BluetoothServerSocket tmp = null;
mTimeout = timeout;
try {
// Secured version: mBluetoothAdapter.listenUsingL2capOn(0x1011, false, false);
if (isBle) {
/* Assigned a dynamic LE_PSM Value */
if (securedConn) {
tmp = mBluetoothAdapter.listenUsingL2capChannel();
} else {
tmp = mBluetoothAdapter.listenUsingInsecureL2capChannel();
}
} else {
if (securedConn) {
tmp = mBluetoothAdapter.listenUsingL2capOn(psmValue);
} else {
tmp = mBluetoothAdapter.listenUsingInsecureL2capOn(psmValue);
}
}
} catch (IOException createSocketException) {
Log.e("Failed to create Coc socket: " + createSocketException.toString());
}
mServerSocket = tmp;
Log.d("AcceptThread: securedConn=" + securedConn + ", Old PSM value=" + psmValue
+ ", new PSM=" + getPsm());
}
public void run() {
try {
mSocket = mServerSocket.accept(mTimeout);
BluetoothConnection conn = new BluetoothConnection(mSocket, mServerSocket);
mConnUuid = addConnection(conn);
Log.d("AcceptThread:run: isConnected=" + mSocket.isConnected() + ", address="
+ mSocket.getRemoteDevice().getAddress() + ", uuid=" + mConnUuid);
} catch (IOException connectException) {
Log.e("AcceptThread:run: Failed to connect socket: " + connectException.toString());
if (mSocket != null) {
cancel();
}
return;
}
}
public void cancel() {
Log.d("AcceptThread:cancel: mmSocket=" + mSocket + ", mmServerSocket=" + mServerSocket);
if (mSocket != null) {
try {
mSocket.close();
} catch (IOException closeException) {
Log.e("Failed to close socket: " + closeException.toString());
}
}
if (mServerSocket != null) {
try {
mServerSocket.close();
} catch (IOException closeException) {
Log.e("Failed to close socket: " + closeException.toString());
}
}
}
public BluetoothSocket getSocket() {
return mSocket;
}
public int getPsm() {
return mServerSocket.getPsm();
}
public String getConnUuid() {
Log.d("ConnectThread::getConnUuid(): mConnUuid=" + mConnUuid);
return mConnUuid;
}
}
}