diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/liveview/LiveviewIoThread.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/liveview/LiveviewIoThread.java
deleted file mode 100644
index 2d50a45fa4..0000000000
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/liveview/LiveviewIoThread.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Copyright (C) 2016-2024 Carsten Pfeiffer, Daniele Gobbetti
-
- This file is part of Gadgetbridge.
-
- Gadgetbridge is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Gadgetbridge is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see . */
-package nodomain.freeyourgadget.gadgetbridge.service.devices.liveview;
-
-import android.bluetooth.BluetoothAdapter;
-import android.content.Context;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.util.UUID;
-
-import nodomain.freeyourgadget.gadgetbridge.devices.liveview.LiveviewConstants;
-import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
-import nodomain.freeyourgadget.gadgetbridge.service.btclassic.BtClassicIoThread;
-import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
-import nodomain.freeyourgadget.gadgetbridge.util.GB;
-
-public class LiveviewIoThread extends BtClassicIoThread {
- private static final Logger LOG = LoggerFactory.getLogger(LiveviewIoThread.class);
-
- private static final UUID SERIAL = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
-
- public LiveviewIoThread(GBDevice gbDevice, Context context, GBDeviceProtocol lvProtocol, LiveviewSupport lvSupport, BluetoothAdapter lvBtAdapter) {
- super(gbDevice, context, lvProtocol, lvSupport, lvBtAdapter);
- }
-
- @Override
- protected byte[] parseIncoming(InputStream inputStream) throws IOException {
- ByteArrayOutputStream msgStream = new ByteArrayOutputStream();
-
- boolean finished = false;
- ReaderState state = ReaderState.ID;
- byte[] incoming = new byte[1];
-
- while (!finished) {
- inputStream.read(incoming);
- msgStream.write(incoming);
-
- switch (state) {
- case ID:
- state = ReaderState.HEADER_LEN;
- incoming = new byte[1];
- break;
- case HEADER_LEN:
- int headerSize = 0xff & incoming[0];
- state = ReaderState.HEADER;
- incoming = new byte[headerSize];
- break;
- case HEADER:
- int payloadSize = getLastInt(msgStream);
- if (payloadSize < 0 || payloadSize > 8000) //this will possibly be changed in the future
- throw new IOException();
- state = ReaderState.PAYLOAD;
- incoming = new byte[payloadSize];
- break;
- case PAYLOAD: //read is blocking, if we are here we have all the data
- finished = true;
- break;
- }
- }
- byte[] msgArray = msgStream.toByteArray();
- LOG.debug("received: " + GB.hexdump(msgArray, 0, msgArray.length));
- return msgArray;
- }
-
-
- /**
- * Enumeration containing the possible internal status of the reader.
- */
- private enum ReaderState {
- ID, HEADER_LEN, HEADER, PAYLOAD;
- }
-
- private int getLastInt(ByteArrayOutputStream stream) {
- byte[] array = stream.toByteArray();
- ByteBuffer buffer = ByteBuffer.wrap(array, array.length - 4, 4);
- buffer.order(LiveviewConstants.BYTE_ORDER);
- return buffer.getInt();
- }
-}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/liveview/LiveviewSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/liveview/LiveviewSupport.java
index e44818fcf6..1c7da25a6e 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/liveview/LiveviewSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/liveview/LiveviewSupport.java
@@ -17,28 +17,94 @@
along with this program. If not, see . */
package nodomain.freeyourgadget.gadgetbridge.service.devices.liveview;
-import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractSerialDeviceSupport;
-import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceIoThread;
-import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+import nodomain.freeyourgadget.gadgetbridge.devices.liveview.LiveviewConstants;
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+import nodomain.freeyourgadget.gadgetbridge.service.btbr.TransactionBuilder;
+import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractSerialDeviceSupportV2;
+
+public class LiveviewSupport extends AbstractSerialDeviceSupportV2 {
+ private static final Logger LOG = LoggerFactory.getLogger(LiveviewSupport.class);
+
+ private final ByteBuffer packetBuffer = ByteBuffer.allocate(8000).order(LiveviewConstants.BYTE_ORDER);
+
+ public LiveviewSupport() {
+ super(8000);
+ addSupportedService(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
+ }
-public class LiveviewSupport extends AbstractSerialDeviceSupport {
@Override
- protected GBDeviceProtocol createDeviceProtocol() {
+ protected LiveviewProtocol createDeviceProtocol() {
return new LiveviewProtocol(getDevice());
}
@Override
- protected GBDeviceIoThread createDeviceIOThread() {
- return new LiveviewIoThread(getDevice(), getContext(), getDeviceProtocol(), LiveviewSupport.this, getBluetoothAdapter());
+ protected TransactionBuilder initializeDevice(final TransactionBuilder builder) {
+ packetBuffer.clear();
+ builder.write(mDeviceProtocol.encodeSetTime());
+ builder.setDeviceState(GBDevice.State.INITIALIZED);
+ return builder;
}
@Override
- public boolean useAutoConnect() {
- return false;
+ public void onSocketRead(final byte[] data) {
+ packetBuffer.put(data);
+ packetBuffer.flip();
+
+ while (packetBuffer.hasRemaining()) {
+ final int start = packetBuffer.position();
+ packetBuffer.mark();
+
+ if (packetBuffer.remaining() < 2) {
+ // not enough bytes for min packet
+ packetBuffer.reset();
+ break;
+ }
+
+ packetBuffer.get(); // id
+
+ final int headerLength = packetBuffer.get() & 0xff;
+ if (packetBuffer.remaining() < headerLength) {
+ // not enough bytes
+ packetBuffer.reset();
+ break;
+ }
+
+ final byte[] header = new byte[headerLength];
+ packetBuffer.get(header);
+
+ final int payloadSize = getLastInt(header);
+ if (packetBuffer.remaining() < payloadSize) {
+ // not enough bytes
+ packetBuffer.reset();
+ break;
+ }
+
+ final int end = packetBuffer.position() + payloadSize;
+
+ final byte[] packet = new byte[end - start];
+ packetBuffer.position(start);
+ packetBuffer.get(packet);
+
+ // Handle it upstream, to the protocol
+ try {
+ super.onSocketRead(packet);
+ } catch (final Exception e) {
+ LOG.error("Failed to handle command", e);
+ }
+ }
+
+ packetBuffer.compact();
}
- @Override
- public synchronized LiveviewIoThread getDeviceIOThread() {
- return (LiveviewIoThread) super.getDeviceIOThread();
+ private int getLastInt(final byte[] array) {
+ final ByteBuffer buffer = ByteBuffer.wrap(array, array.length - 4, 4);
+ buffer.order(LiveviewConstants.BYTE_ORDER);
+ return buffer.getInt();
}
}