1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-10-06 13:20:30 +02:00

Huawei: Improve watchface install support

* there are newer watchface files, which need to unpack inner
com.huawei.watchface as zip file and install watchface.bin
* also some description.xml has BOM which cause issue parsing as xml
This commit is contained in:
Vitaliy Tomin 2024-07-21 14:22:55 +08:00 committed by José Rebelo
parent b8a2fc0076
commit 5c5c0a48d4
6 changed files with 49 additions and 16 deletions

View File

@ -567,6 +567,8 @@ public class HuaweiPacket {
return new Watchface.DeviceWatchInfo.Response(paramsProvider).fromPacket(this);
case Watchface.WatchfaceNameInfo.id:
return new Watchface.WatchfaceNameInfo.Response(paramsProvider).fromPacket(this);
case Watchface.WatchfaceConfirm.id:
return new Watchface.WatchfaceConfirm.Response(paramsProvider).fromPacket(this);
default:
this.isEncrypted = this.attemptDecrypt(); // Helps with debugging
return this;

View File

@ -198,9 +198,18 @@ public class Watchface {
}
public static class Response extends HuaweiPacket {
public static byte reportType = 0;
public Response (ParamsProvider paramsProvider) {
super(paramsProvider);
}
@Override
public void parseTlv() throws HuaweiPacket.ParseException {
if(this.tlv.contains(0x03)) {
this.reportType = this.tlv.getByte(0x03);
}
}
}
}

View File

@ -457,11 +457,6 @@ public class AsynchronousResponse {
support.onUploadProgress(R.string.updatefirmwareoperation_update_complete, 100, false);
SendFileUploadComplete sendFileUploadComplete = new SendFileUploadComplete(this.support, support.huaweiUploadManager.getFileType());
sendFileUploadComplete.doPerform();
if (support.huaweiUploadManager.getFileType() == FileUpload.Filetype.watchface) {
//make uploaded watchface active
SendWatchfaceOperation sendWatchfaceOperation = new SendWatchfaceOperation(this.support, support.huaweiUploadManager.getFileName(), Watchface.WatchfaceOperation.operationActive);
sendWatchfaceOperation.doPerform();
}
} catch (IOException e) {
LOG.error("Could not send fileupload result request", e);
}
@ -473,10 +468,16 @@ public class AsynchronousResponse {
if (response.serviceId == Watchface.id) {
if (response.commandId == Watchface.WatchfaceConfirm.id) {
try {
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.doPerform();
if (resp.reportType == 0x02) {
//make uploaded watchface active
SendWatchfaceOperation sendWatchfaceOperation = new SendWatchfaceOperation(this.support, support.huaweiUploadManager.getFileName(), Watchface.WatchfaceOperation.operationActive);
sendWatchfaceOperation.doPerform();
}
} catch (IOException e) {
LOG.error("Could not send watchface confirm request", e);
}

View File

@ -27,8 +27,10 @@ import org.slf4j.LoggerFactory;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileUpload;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.GBZipFile;
import nodomain.freeyourgadget.gadgetbridge.util.UriHelper;
import nodomain.freeyourgadget.gadgetbridge.util.ZipFileException;
@ -85,13 +87,37 @@ public class HuaweiFwHelper {
final UriHelper uriHelper = UriHelper.get(uri, this.mContext);
GBZipFile watchfacePackage = new GBZipFile(uriHelper.openInputStream());
String xmlDescription = new String(watchfacePackage.getFileFromZip("description.xml"));
byte[] bytesDescription = watchfacePackage.getFileFromZip("description.xml");
// check if description file contents BOM
ByteBuffer bb = ByteBuffer.wrap(bytesDescription);
byte[] bom = new byte[3];
// get the first 3 bytes
bb.get(bom, 0, bom.length);
String content = new String(GB.hexdump(bom));
String xmlDescription = null;
if ("efbbbf".equalsIgnoreCase(content)) {
byte[] contentAfterFirst3Bytes = new byte[bytesDescription.length - 3];
bb.get(contentAfterFirst3Bytes, 0, contentAfterFirst3Bytes.length);
xmlDescription = new String(contentAfterFirst3Bytes);
} else {
xmlDescription = new String(bytesDescription);
}
watchfaceDescription = new HuaweiWatchfaceManager.WatchfaceDescription(xmlDescription);
if (watchfacePackage.fileExists("preview/cover.jpg")) {
final byte[] preview = watchfacePackage.getFileFromZip("preview/cover.jpg");
watchfacePreviewBitmap = BitmapFactory.decodeByteArray(preview, 0, preview.length);
}
fw = watchfacePackage.getFileFromZip("com.huawei.watchface");
byte[] watchfaceZip = watchfacePackage.getFileFromZip("com.huawei.watchface");
try {
GBZipFile watchfaceBinZip = new GBZipFile(watchfaceZip);
fw = watchfaceBinZip.getFileFromZip("watchface.bin");
} catch (ZipFileException e) {
LOG.error("Unable to get watchfaceZip, it seems older already watchface.bin");
fw = watchfaceZip;
}
fileSize = fw.length;
isWatchface = true;

View File

@ -20,10 +20,6 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import android.net.Uri;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@ -31,9 +27,6 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileUpload.FileUploadParams;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.GBZipFile;
import nodomain.freeyourgadget.gadgetbridge.util.UriHelper;
import nodomain.freeyourgadget.gadgetbridge.util.ZipFileException;
public class HuaweiUploadManager {
private static final Logger LOG = LoggerFactory.getLogger(HuaweiUploadManager.class);

View File

@ -82,6 +82,8 @@ public class HuaweiWatchfaceManager
}
public String screenByThemeVersion(String themeVersion) {
if(!map.containsKey(themeVersion))
return "0x0";
String screen = map.get(themeVersion).toString();
return screen;
}