mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-10-21 14:38:19 +00:00
Compare commits
4 Commits
master
...
albertvaka
Author | SHA1 | Date | |
---|---|---|---|
|
6bae0d7503 | ||
|
f27fdbf52e | ||
|
0c14b3fb1a | ||
|
f4a0c53ca0 |
@@ -25,15 +25,14 @@ import java.util.UUID
|
|||||||
import kotlin.text.Charsets.UTF_8
|
import kotlin.text.Charsets.UTF_8
|
||||||
|
|
||||||
class BluetoothLink(
|
class BluetoothLink(
|
||||||
context: Context?,
|
context: Context,
|
||||||
connection: ConnectionMultiplexer,
|
private val connection: ConnectionMultiplexer,
|
||||||
val input: InputStream,
|
val input: InputStream,
|
||||||
val output: OutputStream,
|
val output: OutputStream,
|
||||||
val remoteAddress: BluetoothDevice,
|
val remoteAddress: BluetoothDevice,
|
||||||
val theDeviceInfo: DeviceInfo,
|
val theDeviceInfo: DeviceInfo,
|
||||||
val linkProvider: BluetoothLinkProvider
|
val linkProvider: BluetoothLinkProvider
|
||||||
) : BaseLink(context!!, linkProvider) {
|
) : BaseLink(context, linkProvider) {
|
||||||
private val connection: ConnectionMultiplexer? = connection
|
|
||||||
private var continueAccepting = true
|
private var continueAccepting = true
|
||||||
private val receivingThread = Thread(object : Runnable {
|
private val receivingThread = Thread(object : Runnable {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
@@ -99,13 +98,10 @@ class BluetoothLink(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun disconnect() {
|
override fun disconnect() {
|
||||||
if (connection == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
continueAccepting = false
|
continueAccepting = false
|
||||||
try {
|
try {
|
||||||
connection.close()
|
connection.close()
|
||||||
} catch (ignored: IOException) {
|
} catch (_: IOException) {
|
||||||
}
|
}
|
||||||
linkProvider.disconnectedLink(this, remoteAddress)
|
linkProvider.disconnectedLink(this, remoteAddress)
|
||||||
}
|
}
|
||||||
@@ -124,7 +120,7 @@ class BluetoothLink(
|
|||||||
return try {
|
return try {
|
||||||
var transferUuid: UUID? = null
|
var transferUuid: UUID? = null
|
||||||
if (np.hasPayload()) {
|
if (np.hasPayload()) {
|
||||||
transferUuid = connection!!.newChannel()
|
transferUuid = connection.newChannel()
|
||||||
val payloadTransferInfo = JSONObject()
|
val payloadTransferInfo = JSONObject()
|
||||||
payloadTransferInfo.put("uuid", transferUuid.toString())
|
payloadTransferInfo.put("uuid", transferUuid.toString())
|
||||||
np.payloadTransferInfo = payloadTransferInfo
|
np.payloadTransferInfo = payloadTransferInfo
|
||||||
@@ -132,7 +128,7 @@ class BluetoothLink(
|
|||||||
sendMessage(np)
|
sendMessage(np)
|
||||||
if (transferUuid != null) {
|
if (transferUuid != null) {
|
||||||
try {
|
try {
|
||||||
connection!!.getChannelOutputStream(transferUuid).use { payloadStream ->
|
connection.getChannelOutputStream(transferUuid).use { payloadStream ->
|
||||||
val BUFFER_LENGTH = 1024
|
val BUFFER_LENGTH = 1024
|
||||||
val buffer = ByteArray(BUFFER_LENGTH)
|
val buffer = ByteArray(BUFFER_LENGTH)
|
||||||
var bytesRead: Int
|
var bytesRead: Int
|
||||||
|
@@ -133,6 +133,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
override fun close() {
|
override fun close() {
|
||||||
flush()
|
flush()
|
||||||
lock.withLock {
|
lock.withLock {
|
||||||
|
if (!open) return
|
||||||
open = false
|
open = false
|
||||||
readBuffer.clear()
|
readBuffer.clear()
|
||||||
lockCondition.signalAll()
|
lockCondition.signalAll()
|
||||||
@@ -158,7 +159,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
if (freeWriteAmount == 0) {
|
if (freeWriteAmount == 0) {
|
||||||
try {
|
try {
|
||||||
lockCondition.await()
|
lockCondition.await()
|
||||||
} catch (ignored: Exception) {
|
} catch (_: Exception) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
@@ -177,9 +178,9 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var socket: BluetoothSocket?
|
private val socket: BluetoothSocket
|
||||||
private val channels: MutableMap<UUID, Channel> = HashMap()
|
private val channels: MutableMap<UUID, Channel> = HashMap()
|
||||||
private val lock = ReentrantLock()
|
private val channelsLock = ReentrantLock()
|
||||||
private var open = true
|
private var open = true
|
||||||
private var receivedProtocolVersion = false
|
private var receivedProtocolVersion = false
|
||||||
|
|
||||||
@@ -199,27 +200,27 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
message.position(19)
|
message.position(19)
|
||||||
message.putShort(1.toShort())
|
message.putShort(1.toShort())
|
||||||
message.putShort(1.toShort())
|
message.putShort(1.toShort())
|
||||||
socket!!.outputStream.write(data)
|
socket.outputStream.write(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleException(@Suppress("UNUSED_PARAMETER") ignored: Exception) {
|
private fun handleException(@Suppress("UNUSED_PARAMETER") ignored: Exception) {
|
||||||
lock.withLock {
|
channelsLock.withLock {
|
||||||
open = false
|
open = false
|
||||||
for (channel in channels.values) {
|
for (channel in channels.values) {
|
||||||
channel.doClose()
|
channel.doClose()
|
||||||
}
|
}
|
||||||
channels.clear()
|
channels.clear()
|
||||||
if (socket != null && socket!!.isConnected) {
|
if (socket.isConnected) {
|
||||||
try {
|
try {
|
||||||
socket!!.close()
|
socket.close()
|
||||||
} catch (ignored: IOException) {
|
} catch (_: IOException) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun closeChannel(id: UUID) {
|
private fun closeChannel(id: UUID) {
|
||||||
lock.withLock {
|
channelsLock.withLock {
|
||||||
if (channels.containsKey(id)) {
|
if (channels.containsKey(id)) {
|
||||||
channels.remove(id)
|
channels.remove(id)
|
||||||
val data = ByteArray(19)
|
val data = ByteArray(19)
|
||||||
@@ -230,7 +231,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
message.putLong(id.mostSignificantBits)
|
message.putLong(id.mostSignificantBits)
|
||||||
message.putLong(id.leastSignificantBits)
|
message.putLong(id.leastSignificantBits)
|
||||||
try {
|
try {
|
||||||
socket!!.outputStream.write(data)
|
socket.outputStream.write(data)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
handleException(e)
|
handleException(e)
|
||||||
}
|
}
|
||||||
@@ -239,7 +240,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun readRequest(id: UUID) {
|
private fun readRequest(id: UUID) {
|
||||||
lock.withLock {
|
channelsLock.withLock {
|
||||||
val channel = channels[id] ?: return
|
val channel = channels[id] ?: return
|
||||||
val data = ByteArray(21)
|
val data = ByteArray(21)
|
||||||
channel.lock.withLock {
|
channel.lock.withLock {
|
||||||
@@ -254,7 +255,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
message.putShort(amount.toShort())
|
message.putShort(amount.toShort())
|
||||||
channel.requestedReadAmount += amount
|
channel.requestedReadAmount += amount
|
||||||
try {
|
try {
|
||||||
socket!!.outputStream.write(data)
|
socket.outputStream.write(data)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
handleException(e)
|
handleException(e)
|
||||||
} catch (e: NullPointerException) {
|
} catch (e: NullPointerException) {
|
||||||
@@ -267,7 +268,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
private fun writeRequest(id: UUID, writeData: ByteArray, off: Int, writeLen: Int): Int {
|
private fun writeRequest(id: UUID, writeData: ByteArray, off: Int, writeLen: Int): Int {
|
||||||
lock.withLock {
|
channelsLock.withLock {
|
||||||
val channel = channels[id] ?: return 0
|
val channel = channels[id] ?: return 0
|
||||||
val data = ByteArray(19 + BUFFER_SIZE)
|
val data = ByteArray(19 + BUFFER_SIZE)
|
||||||
var length: Int
|
var length: Int
|
||||||
@@ -296,7 +297,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
channel.lockCondition.signalAll()
|
channel.lockCondition.signalAll()
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
socket!!.outputStream.write(data, 0, 19 + length)
|
socket.outputStream.write(data, 0, 19 + length)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
handleException(e)
|
handleException(e)
|
||||||
}
|
}
|
||||||
@@ -306,29 +307,27 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
private fun flush() {
|
private fun flush() {
|
||||||
lock.withLock {
|
channelsLock.withLock {
|
||||||
if (!open) return
|
if (!open) return
|
||||||
socket!!.outputStream.flush()
|
socket.outputStream.flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
override fun close() {
|
override fun close() {
|
||||||
if (socket == null) {
|
channelsLock.withLock {
|
||||||
return
|
socket.close()
|
||||||
|
for (channel in channels.values) {
|
||||||
|
channel.doClose()
|
||||||
|
}
|
||||||
|
channels.clear()
|
||||||
}
|
}
|
||||||
socket!!.close()
|
|
||||||
socket = null
|
|
||||||
for (channel in channels.values) {
|
|
||||||
channel.doClose()
|
|
||||||
}
|
|
||||||
channels.clear()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
fun newChannel(): UUID {
|
fun newChannel(): UUID {
|
||||||
val id = UUID.randomUUID()
|
val id = UUID.randomUUID()
|
||||||
lock.withLock {
|
channelsLock.withLock {
|
||||||
val data = ByteArray(19)
|
val data = ByteArray(19)
|
||||||
val message = ByteBuffer.wrap(data)
|
val message = ByteBuffer.wrap(data)
|
||||||
message.order(ByteOrder.BIG_ENDIAN)
|
message.order(ByteOrder.BIG_ENDIAN)
|
||||||
@@ -337,7 +336,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
message.putLong(id.mostSignificantBits)
|
message.putLong(id.mostSignificantBits)
|
||||||
message.putLong(id.leastSignificantBits)
|
message.putLong(id.leastSignificantBits)
|
||||||
try {
|
try {
|
||||||
socket!!.outputStream.write(data)
|
socket.outputStream.write(data)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
handleException(e)
|
handleException(e)
|
||||||
throw e
|
throw e
|
||||||
@@ -357,7 +356,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
fun getChannelInputStream(id: UUID): InputStream {
|
fun getChannelInputStream(id: UUID): InputStream {
|
||||||
lock.withLock {
|
channelsLock.withLock {
|
||||||
val channel = channels[id] ?: throw IOException("Invalid channel!")
|
val channel = channels[id] ?: throw IOException("Invalid channel!")
|
||||||
return ChannelInputStream(channel)
|
return ChannelInputStream(channel)
|
||||||
}
|
}
|
||||||
@@ -365,7 +364,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
fun getChannelOutputStream(id: UUID): OutputStream {
|
fun getChannelOutputStream(id: UUID): OutputStream {
|
||||||
lock.withLock {
|
channelsLock.withLock {
|
||||||
val channel = channels[id] ?: throw IOException("Invalid channel!")
|
val channel = channels[id] ?: throw IOException("Invalid channel!")
|
||||||
return ChannelOutputStream(channel)
|
return ChannelOutputStream(channel)
|
||||||
}
|
}
|
||||||
@@ -416,12 +415,12 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
}
|
}
|
||||||
when (type) {
|
when (type) {
|
||||||
MESSAGE_OPEN_CHANNEL -> {
|
MESSAGE_OPEN_CHANNEL -> {
|
||||||
lock.withLock {
|
channelsLock.withLock {
|
||||||
channels.put(channelId, Channel(this@ConnectionMultiplexer, channelId))
|
channels.put(channelId, Channel(this@ConnectionMultiplexer, channelId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MESSAGE_CLOSE_CHANNEL -> {
|
MESSAGE_CLOSE_CHANNEL -> {
|
||||||
lock.withLock {
|
channelsLock.withLock {
|
||||||
val channel = channels[channelId] ?: return
|
val channel = channels[channelId] ?: return
|
||||||
channels.remove(channelId)
|
channels.remove(channelId)
|
||||||
channel.doClose()
|
channel.doClose()
|
||||||
@@ -435,7 +434,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
var amount = ByteBuffer.wrap(data, 0, 2).order(ByteOrder.BIG_ENDIAN).short.toInt()
|
var amount = ByteBuffer.wrap(data, 0, 2).order(ByteOrder.BIG_ENDIAN).short.toInt()
|
||||||
//signed short -> unsigned short (as int) conversion
|
//signed short -> unsigned short (as int) conversion
|
||||||
if (amount < 0) amount += 0x10000
|
if (amount < 0) amount += 0x10000
|
||||||
lock.withLock {
|
channelsLock.withLock {
|
||||||
val channel = channels[channelId] ?: return
|
val channel = channels[channelId] ?: return
|
||||||
channel.lock.withLock {
|
channel.lock.withLock {
|
||||||
channel.freeWriteAmount += amount
|
channel.freeWriteAmount += amount
|
||||||
@@ -448,7 +447,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
throw IOException("Message length is bigger than read size!")
|
throw IOException("Message length is bigger than read size!")
|
||||||
}
|
}
|
||||||
readBuffer(data, length)
|
readBuffer(data, length)
|
||||||
lock.withLock {
|
channelsLock.withLock {
|
||||||
val channel = channels[channelId] ?: return
|
val channel = channels[channelId] ?: return
|
||||||
channel.lock.withLock {
|
channel.lock.withLock {
|
||||||
if (channel.requestedReadAmount < length) {
|
if (channel.requestedReadAmount < length) {
|
||||||
@@ -495,7 +494,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
|
|||||||
|
|
||||||
override fun run() {
|
override fun run() {
|
||||||
while (true) {
|
while (true) {
|
||||||
lock.withLock {
|
channelsLock.withLock {
|
||||||
if (!open) {
|
if (!open) {
|
||||||
Log.w("ConnectionMultiplexer", "connection not open, returning")
|
Log.w("ConnectionMultiplexer", "connection not open, returning")
|
||||||
return
|
return
|
||||||
|
Reference in New Issue
Block a user