From f4322eee7f5ab169f9961644e3019d102e525959 Mon Sep 17 00:00:00 2001 From: Vitaliy Tomin Date: Sun, 21 Jul 2024 21:07:54 +0800 Subject: [PATCH] Huawei: FileUpload refactoring, fixes Watch 3/4 * replaced fileType with fileId which recived on incoming data in 28 03 FileHashSend.Response * width/height in WatchfaceDeviceParams could be int or short (int is present on Watch 3, short is all other tested devices) * use in 27 05 WatchfaceConfirm.Request data recieved in previous WatchfaceConfirm.Response --- .../devices/huawei/HuaweiCoordinator.java | 4 +-- .../devices/huawei/HuaweiPacket.java | 7 +++-- .../devices/huawei/packets/FileUpload.java | 19 ++++++++---- .../devices/huawei/packets/Watchface.java | 29 +++++++++++++++---- .../devices/huawei/AsynchronousResponse.java | 12 +++++--- .../devices/huawei/HuaweiUploadManager.java | 9 ++++++ .../huawei/requests/SendFileUploadChunk.java | 3 +- .../requests/SendFileUploadComplete.java | 8 ++--- .../huawei/requests/SendFileUploadHash.java | 4 ++- 9 files changed, 68 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java index 46d0660a7..156e5d9a5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java @@ -563,11 +563,11 @@ public class HuaweiCoordinator { } public short getWidth() { - return watchfaceDeviceParams.width; + return (short)watchfaceDeviceParams.width; } public short getHeight() { - return watchfaceDeviceParams.height; + return (short)watchfaceDeviceParams.height; } public void setWatchfaceDeviceParams(Watchface.WatchfaceDeviceParams watchfaceDeviceParams) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiPacket.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiPacket.java index e42621ced..06ac8ea0b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiPacket.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiPacket.java @@ -555,6 +555,8 @@ public class HuaweiPacket { return new FileUpload.FileNextChunkParams(paramsProvider).fromPacket(this); case FileUpload.FileUploadConsultAck.id: return new FileUpload.FileUploadConsultAck.Response(paramsProvider).fromPacket(this); + case FileUpload.FileHashSend.id: + return new FileUpload.FileHashSend.Response(paramsProvider).fromPacket(this); default: this.isEncrypted = this.attemptDecrypt(); // Helps with debugging return this; @@ -696,7 +698,7 @@ public class HuaweiPacket { return retv; } - public List serializeFileChunk(byte[] fileChunk, int uploadPosition, short unitSize) { + public List serializeFileChunk(byte[] fileChunk, int uploadPosition, short unitSize, byte fileId) { List retv = new ArrayList<>(); int headerLength = 5; // Magic + (short)(bodyLength + 1) + 0x00 int sliceHeaderLenght =7; @@ -707,7 +709,6 @@ public class HuaweiPacket { ByteBuffer buffer = ByteBuffer.wrap(fileChunk); - byte fileType = 0x01; //TODO: 1 - watchface, 2 - music int sliceStart = uploadPosition; for (int i = 0; i < packetCount; i++) { @@ -724,7 +725,7 @@ public class HuaweiPacket { packet.put(this.serviceId); packet.put(this.commandId); - packet.put(fileType); // Slice + packet.put(fileId); // Slice packet.put((byte)i); // Flag packet.putInt(sliceStart); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FileUpload.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FileUpload.java index 137725590..b94401bfc 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FileUpload.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FileUpload.java @@ -85,35 +85,42 @@ public class FileUpload { public Request(ParamsProvider paramsProvider, byte[] hash, - byte fileType) { + byte fileId) { super(paramsProvider); this.serviceId = FileUpload.id; this.commandId = id; this.tlv = new HuaweiTLV() - .put(0x01, fileType) + .put(0x01, fileId) .put(0x03, hash); this.complete = true; } } public static class Response extends HuaweiPacket { + public byte fileId =0; public Response (ParamsProvider paramsProvider) { super(paramsProvider); } + + @Override + public void parseTlv() throws HuaweiPacket.ParseException { + this.fileId = this.tlv.getByte(0x01); + } + } } public static class FileUploadConsultAck { public static final byte id = 0x04; public static class Request extends HuaweiPacket { - public Request(ParamsProvider paramsProvider, byte noEncryption, byte fileType) { + public Request(ParamsProvider paramsProvider, byte noEncryption, byte fileId) { super(paramsProvider); this.serviceId = FileUpload.id; this.commandId = id; this.tlv = new HuaweiTLV() .put(0x7f, 0x000186A0) //ok - .put(0x01, fileType); + .put(0x01, fileId); if (noEncryption == 1) this.tlv.put(0x09, (byte)0x01); // need on devices which generally encrypted, but files this.complete = true; @@ -176,13 +183,13 @@ public class FileUpload { public static final byte id = 0x07; public static class Request extends HuaweiPacket { - public Request(ParamsProvider paramsProvider, byte fileType) { + public Request(ParamsProvider paramsProvider, byte fileId) { super(paramsProvider); this.serviceId = FileUpload.id; this.commandId = id; this.tlv = new HuaweiTLV() .put(0x7f, 0x000186A0) //ok - .put(0x01, fileType); + .put(0x01, fileId); this.complete = true; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/Watchface.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/Watchface.java index a7742fb6b..c896007b5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/Watchface.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/Watchface.java @@ -29,8 +29,8 @@ public class Watchface { public static class WatchfaceDeviceParams { public String maxVersion = ""; - public short width = 0; - public short height = 0; + public int width = 0; + public int height = 0; public byte supportFileType = 1; public byte sort = 1; public String otherWatchfaceVersions = ""; @@ -112,8 +112,14 @@ public class Watchface { @Override public void parseTlv() throws ParseException { this.params.maxVersion = this.tlv.getString(0x01); - this.params.width = this.tlv.getShort(0x02); - this.params.height = this.tlv.getShort(0x03); + if (this.tlv.getBytes(0x02).length == 4) + this.params.width = this.tlv.getInteger(0x02); + else + this.params.width = this.tlv.getShort(0x02); + if (this.tlv.getBytes(0x03).length == 4) + this.params.height = this.tlv.getInteger(0x03); + else + this.params.height = this.tlv.getShort(0x03); this.params.supportFileType = this.tlv.getByte(0x04); this.params.sort = this.tlv.getByte(0x05); this.params.otherWatchfaceVersions = this.tlv.getString(0x06); @@ -190,24 +196,35 @@ public class Watchface { super(paramsProvider); this.serviceId = Watchface.id; this.commandId = id; + String file = fileName.split("_")[0]; + String version = ""; + try { + version = fileName.split("_")[1]; + } catch (ArrayIndexOutOfBoundsException e) { + + } this.tlv = new HuaweiTLV() - .put(0x01, fileName.split("_")[0]) - .put(0x02, fileName.split("_")[1]) + .put(0x01, file) + .put(0x02, version) .put(0x7f, 0x000186A0); } } public static class Response extends HuaweiPacket { public static byte reportType = 0; + public static String fileName; public Response (ParamsProvider paramsProvider) { super(paramsProvider); } @Override public void parseTlv() throws HuaweiPacket.ParseException { + String name = this.tlv.getString(0x01); + String version = this.tlv.getString(0x02); if(this.tlv.contains(0x03)) { this.reportType = this.tlv.getByte(0x03); } + this.fileName = name + "_" + version; } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/AsynchronousResponse.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/AsynchronousResponse.java index 9ae56ad36..7e440dc91 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/AsynchronousResponse.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/AsynchronousResponse.java @@ -415,6 +415,10 @@ public class AsynchronousResponse { private void handleFileUpload(HuaweiPacket response) throws Request.ResponseParseException { if (response.serviceId == FileUpload.id) { if (response.commandId == FileUpload.FileHashSend.id) { + if (!(response instanceof FileUpload.FileHashSend.Response)) + throw new Request.ResponseTypeMismatchException(response, FileUpload.FileHashSend.Response.class); + FileUpload.FileHashSend.Response resp = (FileUpload.FileHashSend.Response) response; + support.huaweiUploadManager.setFileId(resp.fileId); try { SendFileUploadHash sendFileUploadHash = new SendFileUploadHash(support, support.huaweiUploadManager); sendFileUploadHash.doPerform(); @@ -431,7 +435,7 @@ public class AsynchronousResponse { try { support.huaweiUploadManager.setDeviceBusy(); SendFileUploadAck sendFileUploadAck = new SendFileUploadAck(support, - resp.fileUploadParams.no_encrypt, support.huaweiUploadManager.getFileType()); + resp.fileUploadParams.no_encrypt, support.huaweiUploadManager.getFileId()); sendFileUploadAck.doPerform(); } catch (IOException e) { LOG.error("Could not send fileupload ack request", e); @@ -455,7 +459,7 @@ public class AsynchronousResponse { try { support.huaweiUploadManager.unsetDeviceBusy(); support.onUploadProgress(R.string.updatefirmwareoperation_update_complete, 100, false); - SendFileUploadComplete sendFileUploadComplete = new SendFileUploadComplete(this.support, support.huaweiUploadManager.getFileType()); + SendFileUploadComplete sendFileUploadComplete = new SendFileUploadComplete(this.support, support.huaweiUploadManager.getFileId()); sendFileUploadComplete.doPerform(); } catch (IOException e) { LOG.error("Could not send fileupload result request", e); @@ -471,11 +475,11 @@ public class AsynchronousResponse { if (!(response instanceof Watchface.WatchfaceConfirm.Response)) throw new Request.ResponseTypeMismatchException(response, Watchface.WatchfaceConfirm.class); Watchface.WatchfaceConfirm.Response resp = (Watchface.WatchfaceConfirm.Response) response; - SendWatchfaceConfirm sendWatchfaceConfirm = new SendWatchfaceConfirm(this.support, this.support.huaweiUploadManager.getFileName()); + SendWatchfaceConfirm sendWatchfaceConfirm = new SendWatchfaceConfirm(this.support, resp.fileName); sendWatchfaceConfirm.doPerform(); if (resp.reportType == 0x02) { //make uploaded watchface active - SendWatchfaceOperation sendWatchfaceOperation = new SendWatchfaceOperation(this.support, support.huaweiUploadManager.getFileName(), Watchface.WatchfaceOperation.operationActive); + SendWatchfaceOperation sendWatchfaceOperation = new SendWatchfaceOperation(this.support, resp.fileName, Watchface.WatchfaceOperation.operationActive); sendWatchfaceOperation.doPerform(); } } catch (IOException e) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiUploadManager.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiUploadManager.java index 45af727d9..b73941461 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiUploadManager.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiUploadManager.java @@ -35,6 +35,7 @@ public class HuaweiUploadManager { byte[] fileSHA256; byte fileType = 1; // 1 - watchface, 2 - music, 3 - png for background , 7 - app int fileSize = 0; + byte fileId = 0; // get on incoming (2803) int currentUploadPosition = 0; int uploadChunkSize =0; @@ -90,6 +91,14 @@ public class HuaweiUploadManager { this.fileType = fileType; } + public byte getFileId() { + return fileId; + } + + public void setFileId(byte fileId) { + this.fileId = fileId; + } + public byte[] getFileSHA256() { return fileSHA256; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendFileUploadChunk.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendFileUploadChunk.java index d61cfd3d9..5a3ef31e9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendFileUploadChunk.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendFileUploadChunk.java @@ -39,7 +39,8 @@ public class SendFileUploadChunk extends Request { return new FileUpload.FileNextChunkSend(this.paramsProvider).serializeFileChunk( huaweiUploadManager.getCurrentChunk(), huaweiUploadManager.getCurrentUploadPosition(), - huaweiUploadManager.getUnitSize() + huaweiUploadManager.getUnitSize(), + huaweiUploadManager.getFileId() ); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendFileUploadComplete.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendFileUploadComplete.java index 80a4770d6..93d487623 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendFileUploadComplete.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendFileUploadComplete.java @@ -25,13 +25,13 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupport public class SendFileUploadComplete extends Request { - byte fileType = 0; - public SendFileUploadComplete(HuaweiSupportProvider support, byte fileType) { + byte fileId = 0; + public SendFileUploadComplete(HuaweiSupportProvider support, byte fileId) { super(support); this.serviceId = FileUpload.id; this.commandId = FileUpload.FileUploadResult.id; - this.fileType = fileType; + this.fileId = fileId; this.addToResponse = false; } @@ -39,7 +39,7 @@ public class SendFileUploadComplete extends Request { @Override protected List createRequest() throws RequestCreationException { try { - return new FileUpload.FileUploadResult.Request(this.paramsProvider, this.fileType).serialize(); + return new FileUpload.FileUploadResult.Request(this.paramsProvider, this.fileId).serialize(); } catch (HuaweiPacket.CryptoException e) { throw new RequestCreationException(e); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendFileUploadHash.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendFileUploadHash.java index c86de3f33..074f1892e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendFileUploadHash.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendFileUploadHash.java @@ -26,10 +26,12 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiUploadM public class SendFileUploadHash extends Request{ HuaweiUploadManager huaweiUploadManager; + private byte fileId; public SendFileUploadHash(HuaweiSupportProvider support, HuaweiUploadManager huaweiUploadManager) { super(support); this.huaweiUploadManager = huaweiUploadManager; + this.fileId = fileId; this.serviceId = FileUpload.id; this.commandId = FileUpload.FileHashSend.id; this.addToResponse = false; @@ -41,7 +43,7 @@ public class SendFileUploadHash extends Request{ try { return new FileUpload.FileHashSend.Request(this.paramsProvider, huaweiUploadManager.getFileSHA256(), - huaweiUploadManager.getFileType() + huaweiUploadManager.getFileId() ).serialize(); } catch (HuaweiPacket.CryptoException e) { throw new RequestCreationException(e);