mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-03-13 01:30:09 +01:00
Huawei: initial screenshots support
This commit is contained in:
parent
c6bbda5297
commit
eaf6be424d
@ -649,6 +649,9 @@ public class HuaweiCoordinator {
|
||||
return supportsCommandForService(0x09, 0x0f);
|
||||
}
|
||||
|
||||
public boolean supportDefaultSwitch() {
|
||||
return supportsCommandForService(0x01, 0x21);
|
||||
}
|
||||
|
||||
public boolean supportsExternalCalendarService() {
|
||||
if (supportsExpandCapability())
|
||||
@ -780,7 +783,13 @@ public class HuaweiCoordinator {
|
||||
return supportsExpandCapability(147);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean supportsReverseCapabilities() {
|
||||
if (supportsExpandCapability())
|
||||
return supportsExpandCapability(182);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsPromptPushMessage () {
|
||||
// do not ask for capabilities under specific condition
|
||||
// if (deviceType == 10 && deviceVersion == 73617766697368 && deviceSoftVersion == 372E312E31) -> leo device
|
||||
|
@ -19,6 +19,8 @@ package nodomain.freeyourgadget.gadgetbridge.devices.huawei;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.HUAWEI_MAGIC;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -455,6 +457,8 @@ public class HuaweiPacket {
|
||||
return new DeviceConfig.DeviceStatus.Response(paramsProvider).fromPacket(this);
|
||||
case DeviceConfig.DndLiftWristType.id:
|
||||
return new DeviceConfig.DndLiftWristType.Response(paramsProvider).fromPacket(this);
|
||||
case DeviceConfig.GetDefaultSwitch.id:
|
||||
return new DeviceConfig.GetDefaultSwitch.Response(paramsProvider).fromPacket(this);
|
||||
case DeviceConfig.HiChain.id:
|
||||
return new DeviceConfig.HiChain.Response(paramsProvider).fromPacket(this);
|
||||
case DeviceConfig.PinCode.id:
|
||||
@ -471,6 +475,8 @@ public class HuaweiPacket {
|
||||
return new DeviceConfig.SecurityNegotiation.Response(paramsProvider).fromPacket(this);
|
||||
case DeviceConfig.WearStatus.id:
|
||||
return new DeviceConfig.WearStatus.Response(paramsProvider).fromPacket(this);
|
||||
case DeviceConfig.ReverseCapabilities.id:
|
||||
return new DeviceConfig.ReverseCapabilities.Response(paramsProvider).fromPacket(this);
|
||||
|
||||
// Camera remote has same ID as DeviceConfig
|
||||
case CameraRemote.CameraRemoteStatus.id:
|
||||
@ -677,10 +683,14 @@ public class HuaweiPacket {
|
||||
switch (this.commandId) {
|
||||
case FileDownloadService2C.FileDownloadInit.id:
|
||||
return new FileDownloadService2C.FileDownloadInit.Response(paramsProvider).fromPacket(this);
|
||||
case FileDownloadService2C.FileRequestHash.id:
|
||||
return new FileDownloadService2C.FileRequestHash.Response(paramsProvider).fromPacket(this);
|
||||
case FileDownloadService2C.FileInfo.id:
|
||||
return new FileDownloadService2C.FileInfo.Response(paramsProvider).fromPacket(this);
|
||||
case FileDownloadService2C.BlockResponse.id:
|
||||
return new FileDownloadService2C.BlockResponse(paramsProvider).fromPacket(this);
|
||||
case FileDownloadService2C.IncomingInitRequest.id:
|
||||
return new FileDownloadService2C.IncomingInitRequest.Response(paramsProvider).fromPacket(this);
|
||||
default:
|
||||
this.isEncrypted = this.attemptDecrypt(); // Helps with debugging
|
||||
return this;
|
||||
@ -1090,6 +1100,7 @@ public class HuaweiPacket {
|
||||
return Objects.equals(tlv, that.tlv);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HuaweiPacket{" +
|
||||
|
@ -96,7 +96,7 @@ public class DeviceConfig {
|
||||
this.interval = this.tlv.getShort(0x04);
|
||||
|
||||
System.arraycopy(this.tlv.getBytes(0x05), 2, this.serverNonce, 0, 16);
|
||||
this.authVersion = (byte)this.tlv.getBytes(0x05)[1];
|
||||
this.authVersion = this.tlv.getBytes(0x05)[1];
|
||||
|
||||
if (this.tlv.contains(0x07))
|
||||
this.deviceSupportType = this.tlv.getByte(0x07);
|
||||
@ -116,15 +116,17 @@ public class DeviceConfig {
|
||||
public static class SupportedServices {
|
||||
public static final byte id = 0x02;
|
||||
|
||||
// device should always support service 0x01
|
||||
// notDeviceCapabilities = 0x1C, 0x1E, 0x1F, 0x28, 0x29, 0x2C, 0x2F, 0x31
|
||||
// but services = 0x1E, 0x28, 0x2C, 0x31
|
||||
// service 0x21 depends on MiddleWear support
|
||||
|
||||
public static final byte[] knownSupportedServices = new byte[] {
|
||||
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
|
||||
0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
|
||||
0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1D, 0x20,
|
||||
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x2A, 0x2B, 0x2D, 0x2E,
|
||||
0x30, 0x32, 0x33, 0x34, 0x35
|
||||
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
|
||||
0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
|
||||
0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1D, 0x20,
|
||||
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x2A, 0x2B, 0x2D, 0x2E,
|
||||
0x30, 0x32, 0x33, 0x34, 0x35
|
||||
};
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
@ -803,6 +805,15 @@ public class DeviceConfig {
|
||||
switch (b) {
|
||||
case 0x0:
|
||||
break;
|
||||
case 0x2:
|
||||
this.tlv.put(b); // Force phone manufactures to ""
|
||||
break;
|
||||
case 0x4:
|
||||
this.tlv.put(b); // Force phone model to ""
|
||||
break;
|
||||
case 0x8:
|
||||
this.tlv.put(b, "14"); // Force android version to "14"
|
||||
break;
|
||||
case 0xf:
|
||||
break;
|
||||
case 0x11:
|
||||
@ -964,6 +975,35 @@ public class DeviceConfig {
|
||||
// TODO: set (earphone) double tap action 0x1f
|
||||
// TODO: get (earphone) double tap action 0x20
|
||||
|
||||
public static class GetDefaultSwitch {
|
||||
public static final int id = 0x21;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
public Request(HuaweiPacket.ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
|
||||
this.serviceId = DeviceConfig.id;
|
||||
this.commandId = id;
|
||||
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x01);
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
|
||||
public Response(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTlv() throws ParseException {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class HiChain {
|
||||
public static final int id = 0x28;
|
||||
|
||||
@ -1467,28 +1507,27 @@ public class DeviceConfig {
|
||||
this.serviceId = DeviceConfig.id;
|
||||
this.commandId = id;
|
||||
|
||||
int timestamp = (int) (System.currentTimeMillis() / 1000);
|
||||
long timestamp = System.currentTimeMillis();
|
||||
|
||||
HuaweiTLV software = new HuaweiTLV()
|
||||
.put(0x03, "software_update_service_statement")
|
||||
.put(0x04, 0x01)
|
||||
.put(0x04, (byte)0x01)
|
||||
.put(0x05, "20230508-20230508-0-0")
|
||||
.put(0x06, timestamp);
|
||||
.put(0x06, String.valueOf(timestamp));
|
||||
HuaweiTLV device_information = new HuaweiTLV()
|
||||
.put(0x03, "device_information_management")
|
||||
.put(0x04,0x01)
|
||||
.put(0x04,(byte)0x01)
|
||||
.put(0x05, "20230508-20230508-0-0")
|
||||
.put(0x06,timestamp);
|
||||
|
||||
.put(0x06,String.valueOf(timestamp));
|
||||
HuaweiTLV user_license = new HuaweiTLV()
|
||||
.put(0x03, "user_license_agreement")
|
||||
.put(0x04,0x01)
|
||||
.put(0x04,(byte)0x01)
|
||||
.put(0x05, "20230508-20230508-0-0")
|
||||
.put(0x06,timestamp);
|
||||
.put(0x06,String.valueOf(timestamp));
|
||||
HuaweiTLV tlvList = new HuaweiTLV()
|
||||
.put(0x82, software)
|
||||
.put(0x82,device_information)
|
||||
.put(0x82,user_license);
|
||||
.put(0x82, device_information)
|
||||
.put(0x82, user_license);
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x81, tlvList);
|
||||
}
|
||||
@ -1776,6 +1815,39 @@ public class DeviceConfig {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ReverseCapabilities {
|
||||
public static final int id = 0x3f;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
public Request(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
|
||||
this.serviceId = DeviceConfig.id;
|
||||
this.commandId = id;
|
||||
|
||||
// Bits like ext capabilities
|
||||
byte[] capabilities = {(byte) 0xFD, 0x17};
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x01, capabilities);
|
||||
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
|
||||
public Response(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = DeviceConfig.id;
|
||||
this.commandId = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTlv() throws ParseException {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: wear location enum?
|
||||
|
||||
public static class Date {
|
||||
|
@ -104,6 +104,40 @@ public class FileDownloadService2C {
|
||||
}
|
||||
}
|
||||
|
||||
public static class FileRequestHash {
|
||||
public static final int id = 0x02;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
public Request(ParamsProvider paramsProvider, byte fileId) {
|
||||
super(paramsProvider);
|
||||
|
||||
this.serviceId = FileDownloadService2C.id;
|
||||
this.commandId = id;
|
||||
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x01, fileId)
|
||||
.put(0x02, (byte) 0x01);
|
||||
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
public byte fileId;
|
||||
public byte[] fileHash;
|
||||
|
||||
public Response(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTlv() throws ParseException {
|
||||
fileId = this.tlv.getByte(0x01);
|
||||
fileHash = this.tlv.getBytes(0x03);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class FileInfo {
|
||||
public static final int id = 0x03;
|
||||
|
||||
@ -207,7 +241,7 @@ public class FileDownloadService2C {
|
||||
public static class FileDownloadCompleteRequest extends HuaweiPacket {
|
||||
public static final int id = 0x06;
|
||||
|
||||
public FileDownloadCompleteRequest(ParamsProvider paramsProvider, byte fileId) {
|
||||
public FileDownloadCompleteRequest(ParamsProvider paramsProvider, byte fileId, byte status) {
|
||||
super(paramsProvider);
|
||||
|
||||
this.serviceId = FileDownloadService2C.id;
|
||||
@ -215,9 +249,72 @@ public class FileDownloadService2C {
|
||||
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x01, fileId)
|
||||
.put(0x02, (byte) 1);
|
||||
.put(0x02, status);
|
||||
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class IncomingInitRequest {
|
||||
public static final int id = 0x07;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
public Request(ParamsProvider paramsProvider, String filename, byte fileType, byte fileId, int fileSize, String srcPackage, String dstPackage, String srcFingerprint, String dstFingerprint, byte status) {
|
||||
super(paramsProvider);
|
||||
|
||||
this.serviceId = FileDownloadService2C.id;
|
||||
this.commandId = id;
|
||||
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x01, filename)
|
||||
.put(0x02, fileType)
|
||||
.put(0x03, fileId)
|
||||
.put(0x04, fileSize);
|
||||
|
||||
if (srcPackage != null && dstPackage != null) {
|
||||
this.tlv.put(0x08, srcPackage)
|
||||
.put(0x09, dstPackage)
|
||||
.put(0x0a, srcFingerprint)
|
||||
.put(0x0b, dstFingerprint);
|
||||
}
|
||||
|
||||
this.tlv.put(0x0d, status);
|
||||
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
public String filename;
|
||||
public byte fileType;
|
||||
public byte fileId;
|
||||
public int fileSize;
|
||||
public String description;
|
||||
public String srcPackage;
|
||||
public String dstPackage;
|
||||
public String srcFingerprint = null;
|
||||
public String dstFingerprint = null;
|
||||
|
||||
public Response(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTlv() throws ParseException {
|
||||
filename = this.tlv.getString(0x01);
|
||||
fileType = this.tlv.getByte(0x02);
|
||||
fileId = this.tlv.getByte(0x03);
|
||||
fileSize = this.tlv.getAsInteger(0x4);
|
||||
|
||||
description = this.tlv.getString(0x07);
|
||||
srcPackage = this.tlv.getString(0x08);
|
||||
dstPackage = this.tlv.getString(0x09);
|
||||
if (this.tlv.contains(0x0a))
|
||||
srcFingerprint = this.tlv.getString(0x0a);
|
||||
if (this.tlv.contains(0x0b))
|
||||
dstFingerprint = this.tlv.getString(0x0b);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.DataSync;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.DeviceConfig;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Ephemeris;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.EphemerisFileUpload;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileDownloadService2C;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FindPhone;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.GpsAndTime;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Menstrual;
|
||||
@ -135,6 +136,7 @@ public class AsynchronousResponse {
|
||||
handlePermissionCheck(response);
|
||||
handleDataSyncCommands(response);
|
||||
handleOTA(response);
|
||||
handleFileDownload(response);
|
||||
|
||||
} catch (Request.ResponseParseException e) {
|
||||
LOG.error("Response parse exception", e);
|
||||
@ -831,4 +833,16 @@ public class AsynchronousResponse {
|
||||
support.getHuaweiOTAManager().handleDeviceError(((OTA.DeviceError.Response) response).errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
void handleFileDownload(HuaweiPacket response) throws Request.ResponseTypeMismatchException {
|
||||
if (response.serviceId != FileDownloadService2C.id)
|
||||
return;
|
||||
if (response.commandId == FileDownloadService2C.IncomingInitRequest.id) {
|
||||
if (!(response instanceof FileDownloadService2C.IncomingInitRequest.Response)) {
|
||||
throw new Request.ResponseTypeMismatchException(response, FileDownloadService2C.IncomingInitRequest.class);
|
||||
}
|
||||
FileDownloadService2C.IncomingInitRequest.Response resp = (FileDownloadService2C.IncomingInitRequest.Response) response;
|
||||
support.deviceFileDownloadRequest(resp.filename, resp.fileType, resp.fileId, resp.fileSize, resp.srcPackage, resp.dstPackage, resp.srcFingerprint, resp.dstFingerprint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
@ -38,6 +39,8 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileDownloadS
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetFileBlockRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetFileDownloadCompleteRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetFileDownloadInitRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetFileHashRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetFileIncomingAck;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetFileInfoRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetFileParametersRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.Request;
|
||||
@ -79,6 +82,12 @@ public class HuaweiFileDownloadManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static class HuaweiFileDownloadVerifyException extends HuaweiFileDownloadException {
|
||||
HuaweiFileDownloadVerifyException(@Nullable FileRequest fileRequest) {
|
||||
super(fileRequest, "Verify failed");
|
||||
}
|
||||
}
|
||||
|
||||
public static class HuaweiFileDownloadFileMismatchException extends HuaweiFileDownloadException {
|
||||
HuaweiFileDownloadFileMismatchException(@NonNull FileRequest fileRequest, String filename) {
|
||||
super(fileRequest, "Data for wrong file received. Expected name " + fileRequest.filename + ", got name " + filename);
|
||||
@ -96,9 +105,9 @@ public class HuaweiFileDownloadManager {
|
||||
super(
|
||||
fileRequest,
|
||||
"Data for wrong file received. Expected " +
|
||||
(newSync ?
|
||||
"id " + fileRequest.fileId + ", got id " + number :
|
||||
"packet number " + (fileRequest.lastPacketNumber + 1) + ", got " + number)
|
||||
(newSync ?
|
||||
"id " + fileRequest.fileId + ", got id " + number :
|
||||
"packet number " + (fileRequest.lastPacketNumber + 1) + ", got " + number)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -112,7 +121,8 @@ public class HuaweiFileDownloadManager {
|
||||
}
|
||||
|
||||
public static class FileDownloadCallback {
|
||||
public void downloadComplete(FileRequest fileRequest) { }
|
||||
public void downloadComplete(FileRequest fileRequest) {
|
||||
}
|
||||
|
||||
public void downloadException(HuaweiFileDownloadException e) {
|
||||
if (e.fileRequest != null)
|
||||
@ -129,7 +139,7 @@ public class HuaweiFileDownloadManager {
|
||||
private final FileType fileType;
|
||||
private final boolean newSync;
|
||||
|
||||
FileDownloadCallback fileDownloadCallback = null;
|
||||
private final FileDownloadCallback fileDownloadCallback;
|
||||
|
||||
// Sleep type only - for 2C GPS they are set to zero
|
||||
private int startTime = 0;
|
||||
@ -139,6 +149,9 @@ public class HuaweiFileDownloadManager {
|
||||
private short workoutId;
|
||||
private Long databaseId;
|
||||
|
||||
|
||||
private boolean initFormDevice = false;
|
||||
|
||||
private FileRequest(String filename, FileType fileType, boolean newSync, int startTime, int endTime, FileDownloadCallback fileDownloadCallback) {
|
||||
this.filename = filename;
|
||||
this.fileType = fileType;
|
||||
@ -148,6 +161,10 @@ public class HuaweiFileDownloadManager {
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
public static FileRequest IncomingFileRequest(String filename, FileDownloadCallback fileDownloadCallback) {
|
||||
return new FileRequest(filename, FileType.UNKNOWN, true, fileDownloadCallback);
|
||||
}
|
||||
|
||||
public static FileRequest sleepStateFileRequest(boolean supportsTruSleepNewSync, int startTime, int endTime, FileDownloadCallback fileDownloadCallback) {
|
||||
return new FileRequest("sleep_state.bin", FileType.SLEEP_STATE, supportsTruSleepNewSync, startTime, endTime, fileDownloadCallback);
|
||||
}
|
||||
@ -200,6 +217,15 @@ public class HuaweiFileDownloadManager {
|
||||
// New sync only
|
||||
private byte fileId;
|
||||
private boolean noEncrypt;
|
||||
private boolean needVerify = false;
|
||||
private byte[] fileHash = null;
|
||||
|
||||
// Incoming P2P request
|
||||
private byte inFileType;
|
||||
private String srcPackage = null;
|
||||
private String dstPackage = null;
|
||||
private String srcFingerprint = null;
|
||||
private String dstFingerprint = null;
|
||||
|
||||
public byte getFileId() {
|
||||
return fileId;
|
||||
@ -215,7 +241,7 @@ public class HuaweiFileDownloadManager {
|
||||
|
||||
public byte[] getData() {
|
||||
if (buffer == null)
|
||||
return new byte[] {};
|
||||
return new byte[]{};
|
||||
return buffer.array();
|
||||
}
|
||||
|
||||
@ -250,6 +276,74 @@ public class HuaweiFileDownloadManager {
|
||||
public boolean isNoEncrypt() {
|
||||
return noEncrypt;
|
||||
}
|
||||
|
||||
public boolean isInitFormDevice() {
|
||||
return initFormDevice;
|
||||
}
|
||||
|
||||
public void setInitFormDevice(boolean initFormDevice) {
|
||||
this.initFormDevice = initFormDevice;
|
||||
}
|
||||
|
||||
public String getSrcPackage() {
|
||||
return srcPackage;
|
||||
}
|
||||
|
||||
public void setSrcPackage(String srcPackage) {
|
||||
this.srcPackage = srcPackage;
|
||||
}
|
||||
|
||||
public String getDstPackage() {
|
||||
return dstPackage;
|
||||
}
|
||||
|
||||
public void setDstPackage(String dstPackage) {
|
||||
this.dstPackage = dstPackage;
|
||||
}
|
||||
|
||||
public String getSrcFingerprint() {
|
||||
return srcFingerprint;
|
||||
}
|
||||
|
||||
public void setSrcFingerprint(String srcFingerprint) {
|
||||
this.srcFingerprint = srcFingerprint;
|
||||
}
|
||||
|
||||
public String getDstFingerprint() {
|
||||
return dstFingerprint;
|
||||
}
|
||||
|
||||
public void setDstFingerprint(String dstFingerprint) {
|
||||
this.dstFingerprint = dstFingerprint;
|
||||
}
|
||||
|
||||
public void setFileId(byte fileId) {
|
||||
this.fileId = fileId;
|
||||
}
|
||||
|
||||
public int getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public void setFileSize(int fileSize) {
|
||||
this.fileSize = fileSize;
|
||||
}
|
||||
|
||||
public byte getInFileType() {
|
||||
return inFileType;
|
||||
}
|
||||
|
||||
public void setInFileType(byte inFileType) {
|
||||
this.inFileType = inFileType;
|
||||
}
|
||||
|
||||
public boolean isNeedVerify() {
|
||||
return needVerify;
|
||||
}
|
||||
|
||||
public void setNeedVerify(boolean needVerify) {
|
||||
this.needVerify = needVerify;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -272,9 +366,9 @@ public class HuaweiFileDownloadManager {
|
||||
public boolean handleResponse(HuaweiPacket response) {
|
||||
if (
|
||||
(response.serviceId == FileDownloadService0A.id &&
|
||||
response.commandId == FileDownloadService0A.BlockResponse.id) ||
|
||||
(response.serviceId == FileDownloadService2C.id &&
|
||||
response.commandId == FileDownloadService2C.BlockResponse.id)
|
||||
response.commandId == FileDownloadService0A.BlockResponse.id) ||
|
||||
(response.serviceId == FileDownloadService2C.id &&
|
||||
response.commandId == FileDownloadService2C.BlockResponse.id)
|
||||
) {
|
||||
receivedPacket = response;
|
||||
return true;
|
||||
@ -350,6 +444,14 @@ public class HuaweiFileDownloadManager {
|
||||
if (needSync)
|
||||
this.needSync = true;
|
||||
}
|
||||
if (fileRequest.isInitFormDevice()) {
|
||||
GetFileIncomingAck getFileIncomingAck = new GetFileIncomingAck(supportProvider, fileRequest, (byte) 0);
|
||||
try {
|
||||
getFileIncomingAck.doPerform();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error execute", e);
|
||||
}
|
||||
}
|
||||
startDownload();
|
||||
}
|
||||
|
||||
@ -400,6 +502,11 @@ public class HuaweiFileDownloadManager {
|
||||
|
||||
this.currentFileRequest = this.fileRequests.remove(0);
|
||||
|
||||
if (this.currentFileRequest.isInitFormDevice()) {
|
||||
getFileHash();
|
||||
return;
|
||||
}
|
||||
|
||||
GetFileDownloadInitRequest getFileDownloadInitRequest = new GetFileDownloadInitRequest(supportProvider, currentFileRequest);
|
||||
getFileDownloadInitRequest.setFinalizeReq(new Request.RequestCallback() {
|
||||
@Override
|
||||
@ -514,6 +621,39 @@ public class HuaweiFileDownloadManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void getFileHash() {
|
||||
if (!currentFileRequest.isNeedVerify() || !currentFileRequest.isNewSync()) {
|
||||
getFileInfo();
|
||||
return;
|
||||
}
|
||||
GetFileHashRequest getFileHashRequest = new GetFileHashRequest(supportProvider, currentFileRequest);
|
||||
getFileHashRequest.setFinalizeReq(new Request.RequestCallback() {
|
||||
@Override
|
||||
public void call(Request request) {
|
||||
GetFileHashRequest r = (GetFileHashRequest) request;
|
||||
if (currentFileRequest.fileId != r.fileId) {
|
||||
currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadFileMismatchException(currentFileRequest, r.fileId, true));
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
currentFileRequest.fileHash = r.fileHash;
|
||||
getFileInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleException(Request.ResponseParseException e) {
|
||||
currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadRequestException(null, this.getClass(), e));
|
||||
reset();
|
||||
}
|
||||
});
|
||||
try {
|
||||
getFileHashRequest.doPerform();
|
||||
} catch (IOException e) {
|
||||
currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadSendException(currentFileRequest, getFileHashRequest, e));
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
private void getFileInfo() {
|
||||
GetFileInfoRequest getFileInfoRequest = new GetFileInfoRequest(supportProvider, currentFileRequest);
|
||||
getFileInfoRequest.setFinalizeReq(new Request.RequestCallback() {
|
||||
@ -624,24 +764,52 @@ public class HuaweiFileDownloadManager {
|
||||
// Stop timeout from hitting
|
||||
this.handler.removeCallbacks(this.timeout);
|
||||
|
||||
|
||||
byte status = 1;
|
||||
if (currentFileRequest.isNeedVerify() && currentFileRequest.isNewSync()) {
|
||||
status = 2;
|
||||
try {
|
||||
if (currentFileRequest.fileHash != null) {
|
||||
MessageDigest m = MessageDigest.getInstance("SHA256");
|
||||
m.update(currentFileRequest.getData(), 0, currentFileRequest.fileSize);
|
||||
byte[] sha256 = m.digest();
|
||||
LOG.info("SHA256: {} {}", GB.hexdump(sha256), GB.hexdump(currentFileRequest.fileHash));
|
||||
if (Arrays.equals(sha256, currentFileRequest.fileHash)) {
|
||||
status = 1;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error verify SHA256", e);
|
||||
}
|
||||
}
|
||||
|
||||
// File complete request
|
||||
GetFileDownloadCompleteRequest getFileDownloadCompleteRequest = new GetFileDownloadCompleteRequest(supportProvider, currentFileRequest);
|
||||
GetFileDownloadCompleteRequest getFileDownloadCompleteRequest = new GetFileDownloadCompleteRequest(supportProvider, currentFileRequest, status);
|
||||
try {
|
||||
getFileDownloadCompleteRequest.doPerform();
|
||||
} catch (IOException e) {
|
||||
currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadSendException(currentFileRequest, getFileDownloadCompleteRequest, e));
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (status != 1) {
|
||||
currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadVerifyException(currentFileRequest));
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle file data
|
||||
|
||||
try {
|
||||
currentFileRequest.fileDownloadCallback.downloadComplete(currentFileRequest);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Download complete callback exception.", e);
|
||||
LOG.warn("File contents: {}", GB.hexdump(currentFileRequest.getData()));
|
||||
GB.toast("Workout GPX file could not be parsed.",Toast.LENGTH_SHORT, GB.ERROR, e);
|
||||
GB.toast("Workout GPX file could not be parsed.", Toast.LENGTH_SHORT, GB.ERROR, e);
|
||||
}
|
||||
|
||||
|
||||
if (!this.currentFileRequest.newSync && !this.fileRequests.isEmpty() && !this.fileRequests.get(0).newSync) {
|
||||
// Old sync can potentially take a shortcut
|
||||
if (arrayContains(this.currentFileRequest.filenames, this.fileRequests.get(0).filename)) {
|
||||
@ -660,7 +828,6 @@ public class HuaweiFileDownloadManager {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
|
@ -1,21 +1,37 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTLV;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.P2P;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiBaseP2PService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiP2PWakeAppScreenshot;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendP2PCommand;
|
||||
|
||||
public class HuaweiP2PManager {
|
||||
private final Logger LOG = LoggerFactory.getLogger(HuaweiP2PManager.class);
|
||||
|
||||
public interface HuaweiWakeApp {
|
||||
boolean onWakeApp(HuaweiP2PManager manager, Uri uri);
|
||||
}
|
||||
|
||||
private final HuaweiSupportProvider support;
|
||||
|
||||
private final List<HuaweiBaseP2PService> registeredServices;
|
||||
|
||||
private final Map<String, HuaweiWakeApp> supportedWakeApp;
|
||||
|
||||
private Short sequence = 1;
|
||||
|
||||
public synchronized Short getNextSequence() {
|
||||
@ -25,6 +41,8 @@ public class HuaweiP2PManager {
|
||||
public HuaweiP2PManager(HuaweiSupportProvider support) {
|
||||
this.support = support;
|
||||
this.registeredServices = new ArrayList<>();
|
||||
this.supportedWakeApp = new HashMap<>();
|
||||
this.supportedWakeApp.put("/router/device/screenshot",new HuaweiP2PWakeAppScreenshot());
|
||||
}
|
||||
|
||||
public HuaweiSupportProvider getSupportProvider() {
|
||||
@ -59,9 +77,71 @@ public class HuaweiP2PManager {
|
||||
registeredServices.clear();
|
||||
}
|
||||
|
||||
public void sendAck(short sequence, String srcPackage, String dstPackage, int code) {
|
||||
try {
|
||||
SendP2PCommand test = new SendP2PCommand(this.getSupportProvider(), (byte) 3, sequence, srcPackage, dstPackage, null, null, null, code);
|
||||
test.doPerform();
|
||||
} catch (IOException e) {
|
||||
LOG.error("P2P Service error send ACK", e);
|
||||
}
|
||||
}
|
||||
|
||||
public int handleLink(String link) {
|
||||
if (TextUtils.isEmpty(link) || (!link.startsWith("huaweischeme://healthapp/router/") && !link.startsWith("huaweischeme://healthapp/home/"))) {
|
||||
return 0xd2;
|
||||
}
|
||||
Uri uri = Uri.parse(link);
|
||||
LOG.info("Path: {}", uri.getPath());
|
||||
HuaweiWakeApp svr = supportedWakeApp.get(uri.getPath());
|
||||
if(svr != null && svr.onWakeApp(this, uri)) {
|
||||
return 0xd1; //success
|
||||
}
|
||||
return 0xd2;
|
||||
}
|
||||
|
||||
public int handleWakeApp(P2P.P2PCommand.Response packet) {
|
||||
if (packet.respData == null || packet.respData.length == 0) {
|
||||
return 0xcc;
|
||||
}
|
||||
|
||||
HuaweiTLV tlv = new HuaweiTLV();
|
||||
tlv.parse(packet.respData);
|
||||
String link = "";
|
||||
if(tlv.contains(0x04)) {
|
||||
try {
|
||||
link = tlv.getString(0x04);
|
||||
} catch (HuaweiPacket.MissingTagException e) {
|
||||
LOG.error("P2P Service error get link", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(link)) {
|
||||
return handleLink(link);
|
||||
}
|
||||
// TODO: support other TLV.
|
||||
return 0xcd;
|
||||
}
|
||||
|
||||
|
||||
public void handleFile(String srcPackage, String dstPackage, String srcFingerprint, String dstFingerprint, String filename, byte[] data) {
|
||||
// NOTE: Maybe packet should be found by dstPacket or as a pair package + fingerprint
|
||||
for (HuaweiBaseP2PService service : registeredServices) {
|
||||
if (service.getPackage().equals(srcPackage)) {
|
||||
service.handleFile(filename, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handlePacket(P2P.P2PCommand.Response packet) {
|
||||
LOG.info("P2P Service message: Src: {} Dst: {} Seq: {}", packet.srcPackage, packet.dstPackage, packet.sequenceId);
|
||||
if(packet.cmdId == 1) {
|
||||
String[] split = packet.dstPackage.split("\\.");
|
||||
if (split.length > 2 && split[2].equals("wakeapp")) {
|
||||
int code = handleWakeApp(packet);
|
||||
sendAck(packet.sequenceId, packet.dstPackage, packet.srcPackage, code);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (HuaweiBaseP2PService service : registeredServices) {
|
||||
if (service.getPackage().equals(packet.srcPackage)) {
|
||||
service.handlePacket(packet);
|
||||
|
@ -130,15 +130,16 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetN
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetOTAChangeLog;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetSmartAlarmList;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetWatchfaceParams;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetWorkoutCapability;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendCameraRemoteSetupEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendDeviceReportThreshold;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendExtendedAccountRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendFitnessUserInfoRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendGetDefaultSwitch;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendGpsDataRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendFileUploadInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendHeartRateZonesConfig;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendOTASetAutoUpdate;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendReverseCapabilitiesRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendRunPaceConfigRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendSetContactsRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendNotifyHeartRateCapabilityRequest;
|
||||
@ -823,13 +824,14 @@ public class HuaweiSupportProvider {
|
||||
initRequestQueue.add(new SendExtendedAccountRequest(this));
|
||||
initRequestQueue.add(new GetSettingRelatedRequest(this));
|
||||
initRequestQueue.add(new AcceptAgreementsRequest(this));
|
||||
initRequestQueue.add(new SendReverseCapabilitiesRequest(this));
|
||||
initRequestQueue.add(new SendSetUpDeviceStatusRequest(this));
|
||||
initRequestQueue.add(new GetActivityTypeRequest(this));
|
||||
initRequestQueue.add(new GetWearStatusRequest(this));
|
||||
initRequestQueue.add(new GetConnectStatusRequest(this));
|
||||
initRequestQueue.add(new GetDndLiftWristTypeRequest(this));
|
||||
initRequestQueue.add(new SendDndDeleteRequest(this));
|
||||
initRequestQueue.add(new SendDndAddRequest(this));
|
||||
initRequestQueue.add(new SendSetUpDeviceStatusRequest(this));
|
||||
initRequestQueue.add(new GetWearStatusRequest(this));
|
||||
initRequestQueue.add(new SendMenstrualCapabilityRequest(this));
|
||||
initRequestQueue.add(new SendNotifyHeartRateCapabilityRequest(this));
|
||||
initRequestQueue.add(new SendNotifyRestHeartRateCapabilityRequest(this));
|
||||
@ -844,6 +846,7 @@ public class HuaweiSupportProvider {
|
||||
initRequestQueue.add(new GetWatchfaceParams(this));
|
||||
initRequestQueue.add(new SendCameraRemoteSetupEvent(this, CameraRemote.CameraRemoteSetup.Request.Event.ENABLE_CAMERA));
|
||||
initRequestQueue.add(new GetAppInfoParams(this));
|
||||
initRequestQueue.add(new SendGetDefaultSwitch(this));
|
||||
initRequestQueue.add(new GetMusicInfoParams(this));
|
||||
initRequestQueue.add(new GetExtendedMusicInfoParams(this));
|
||||
initRequestQueue.add(new SetActivateOnLiftRequest(this));
|
||||
@ -2506,6 +2509,35 @@ public class HuaweiSupportProvider {
|
||||
this.huaweiDataSyncTreeCircleGoals = null;
|
||||
}
|
||||
|
||||
public void deviceFileDownloadRequest(String filename, byte fileType, byte fileId, int fileSize, String srcPackage, String dstPackage, String srcFingerprint, String dstFingerprint) {
|
||||
HuaweiFileDownloadManager.FileRequest request = HuaweiFileDownloadManager.FileRequest.IncomingFileRequest(filename, new HuaweiFileDownloadManager.FileDownloadCallback() {
|
||||
@Override
|
||||
public void downloadComplete(HuaweiFileDownloadManager.FileRequest fileRequest) {
|
||||
LOG.info("Download file: {}", fileRequest.getFilename());
|
||||
huaweiP2PManager.handleFile(fileRequest.getSrcPackage(), fileRequest.getDstPackage(), fileRequest.getSrcFingerprint(), fileRequest.getDstFingerprint(), fileRequest.getFilename(), fileRequest.getData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadException(HuaweiFileDownloadManager.HuaweiFileDownloadException e) {
|
||||
super.downloadException(e);
|
||||
LOG.debug("Download exception");
|
||||
}
|
||||
});
|
||||
|
||||
request.setInitFormDevice(true);
|
||||
request.setInFileType(fileType);
|
||||
request.setFileId(fileId);
|
||||
request.setFileSize(fileSize);
|
||||
request.setSrcPackage(srcPackage);
|
||||
request.setDstPackage(dstPackage);
|
||||
request.setSrcFingerprint(srcFingerprint);
|
||||
request.setDstFingerprint(dstFingerprint);
|
||||
request.setNeedVerify(true);
|
||||
|
||||
huaweiFileDownloadManager.addToQueue(request, false);
|
||||
|
||||
}
|
||||
|
||||
public boolean downloadTruSleepData(int start, int end) {
|
||||
// We only get the data if TruSleep is supported
|
||||
if (!getHuaweiCoordinator().supportsTruSleep())
|
||||
|
@ -81,15 +81,6 @@ public abstract class HuaweiBaseP2PService {
|
||||
}
|
||||
}
|
||||
|
||||
public void sendAck(short sequence, String srcPackage, String dstPackage, int code) {
|
||||
try {
|
||||
SendP2PCommand test = new SendP2PCommand(this.manager.getSupportProvider(), (byte) 3, sequence, srcPackage, dstPackage, null, null, null, code);
|
||||
test.doPerform();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void handlePacket(P2P.P2PCommand.Response packet) {
|
||||
LOG.info("HuaweiBaseP2PService handlePacket: {} Code: {}", packet.cmdId, packet.respCode);
|
||||
if (waitPackets.containsKey(packet.sequenceId)) {
|
||||
@ -101,14 +92,17 @@ public abstract class HuaweiBaseP2PService {
|
||||
LOG.error("HuaweiBaseP2PService handler is null");
|
||||
}
|
||||
} else {
|
||||
|
||||
if (packet.cmdId == 1) { //Ping
|
||||
sendAck(packet.sequenceId, packet.dstPackage, packet.srcPackage, 0xca);
|
||||
manager.sendAck(packet.sequenceId, packet.dstPackage, packet.srcPackage, 0xcf);
|
||||
} else if (packet.cmdId == 2) {
|
||||
manager.sendAck(packet.sequenceId, packet.dstPackage, packet.srcPackage, 0xcf);
|
||||
handleData(packet.respData);
|
||||
sendAck(packet.sequenceId, packet.dstPackage, packet.srcPackage, 0xca);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleFile(String filename, byte[] data) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,348 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PaintFlagsDrawFilter;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.provider.MediaStore;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiP2PManager;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
|
||||
public class HuaweiP2PScreenshotService extends HuaweiBaseP2PService {
|
||||
private final Logger LOG = LoggerFactory.getLogger(HuaweiP2PScreenshotService.class);
|
||||
|
||||
public static final String MODULE = "hw.unitedevice.screenshot";
|
||||
|
||||
public static class DeviceInfo {
|
||||
@SerializedName("bezierCurvePoint")
|
||||
public BezierCurvePoint bezierCurvePoint;
|
||||
@SerializedName("cutout")
|
||||
public int cutout;
|
||||
@SerializedName("compressionAlgorithm")
|
||||
public int compressionAlgorithm;
|
||||
@SerializedName("photoHeight")
|
||||
public int photoHeight;
|
||||
@SerializedName("radius")
|
||||
public float[] radius;
|
||||
@SerializedName("photoWidth")
|
||||
public int photoWidth;
|
||||
@SerializedName("roundedCutType")
|
||||
public int roundedCutType;
|
||||
@SerializedName("startPointX")
|
||||
public int startPointX;
|
||||
@SerializedName("startPointY")
|
||||
public int startPointY;
|
||||
@SerializedName("watchType")
|
||||
public int watchType;
|
||||
|
||||
public static class BezierCurvePoint {
|
||||
@SerializedName("inPoint")
|
||||
public float[][] inPoint;
|
||||
@SerializedName("outPoint")
|
||||
public float[][] outPoint;
|
||||
}
|
||||
}
|
||||
|
||||
// Crop related constants.
|
||||
private final int PIXELS_TO_CROP = 1;
|
||||
private final int CROP_BORDER_WIDTH = 2;
|
||||
private final int CROP_BORDER_COLOR = Color.BLACK;
|
||||
private final int CROP_BACKGROUND_COLOR = Color.WHITE;
|
||||
|
||||
private DeviceInfo deviceInfo = null;
|
||||
|
||||
public HuaweiP2PScreenshotService(HuaweiP2PManager manager) {
|
||||
super(manager);
|
||||
LOG.info("HuaweiP2PScreenshotService");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModule() {
|
||||
return HuaweiP2PScreenshotService.MODULE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPackage() {
|
||||
return "com.huawei.watch.screenshot";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFingerprint() {
|
||||
return "SystemApp";
|
||||
}
|
||||
|
||||
private String startServiceData() {
|
||||
JSONObject data = new JSONObject();
|
||||
try {
|
||||
data.put("operateType", 1);
|
||||
data.put("statusCode", 1);
|
||||
data.put("hasPermission", 1);
|
||||
} catch (JSONException e) {
|
||||
LOG.error("startServiceData: Failed to prepare JSOM Object", e);
|
||||
}
|
||||
return data.toString();
|
||||
}
|
||||
|
||||
private String createResponse(int i) {
|
||||
JSONObject data = new JSONObject();
|
||||
try {
|
||||
data.put("operateType", 3);
|
||||
data.put("statusCode", i);
|
||||
} catch (JSONException e) {
|
||||
LOG.error("createResponse: Failed to prepare JSOM Object", e);
|
||||
}
|
||||
return data.toString();
|
||||
}
|
||||
|
||||
private String createDownloadResponse(String filename, int i) {
|
||||
JSONObject data = new JSONObject();
|
||||
try {
|
||||
data.put("operateType", 2);
|
||||
data.put("fileName", filename);
|
||||
data.put("statusCode", i);
|
||||
} catch (JSONException e) {
|
||||
LOG.error("createResponse: Failed to prepare JSOM Object", e);
|
||||
}
|
||||
return data.toString();
|
||||
}
|
||||
|
||||
public void sendNegotiateConfig() {
|
||||
String packet = startServiceData();
|
||||
LOG.info("HuaweiP2PScreenshotService sendNegotiateConfig");
|
||||
sendCommand(packet.getBytes(StandardCharsets.UTF_8), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registered() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleData(byte[] data) {
|
||||
if (data == null) {
|
||||
LOG.error("HuaweiP2PScreenshotService data is null");
|
||||
return;
|
||||
}
|
||||
String config = new String(data, StandardCharsets.UTF_8);
|
||||
if (TextUtils.isEmpty(config)) {
|
||||
LOG.error("HuaweiP2PScreenshotService config is empty");
|
||||
return;
|
||||
}
|
||||
LOG.info("HuaweiP2PScreenshotService handleData: {}", config);
|
||||
DeviceInfo deviceInfo = null;
|
||||
try {
|
||||
deviceInfo = new Gson().fromJson(config, DeviceInfo.class);
|
||||
} catch (JsonSyntaxException e) {
|
||||
LOG.error("HuaweiP2PScreenshotService error parse config", e);
|
||||
}
|
||||
|
||||
int status = 2;
|
||||
if (deviceInfo == null) {
|
||||
LOG.error("HuaweiP2PScreenshotService deviceInfo is null");
|
||||
} else {
|
||||
if (deviceInfo.compressionAlgorithm == 1) {
|
||||
status = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (status == 1) {
|
||||
this.deviceInfo = deviceInfo;
|
||||
}
|
||||
sendCommand(createResponse(status).getBytes(StandardCharsets.UTF_8), null);
|
||||
}
|
||||
|
||||
private int getWightWithoutCropPixels(int width) {
|
||||
return width - PIXELS_TO_CROP * 2; // crop from both sides.
|
||||
}
|
||||
|
||||
private int getHeightWithoutCropPixels(int height) {
|
||||
return height - PIXELS_TO_CROP * 2; // crop from both sides.
|
||||
}
|
||||
|
||||
private Bitmap prepareCroppedImageCircle(Bitmap image) {
|
||||
int cropWidth = getWightWithoutCropPixels(this.deviceInfo.photoWidth);
|
||||
int cropHeight = getHeightWithoutCropPixels(this.deviceInfo.photoHeight);
|
||||
int width = getWightWithoutCropPixels(this.deviceInfo.photoWidth) + CROP_BORDER_WIDTH * 2; // we have border on both sides
|
||||
int height = getHeightWithoutCropPixels(this.deviceInfo.photoHeight) + CROP_BORDER_WIDTH * 2; // we have border on both sides
|
||||
Bitmap createBitmap = Bitmap.createBitmap(width, height, image.getConfig());
|
||||
Canvas canvas = new Canvas(createBitmap);
|
||||
canvas.drawColor(CROP_BACKGROUND_COLOR);
|
||||
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(CROP_BORDER_WIDTH);
|
||||
paint.setColor(CROP_BORDER_COLOR);
|
||||
canvas.drawCircle(((float) width) / 2.0f, ((float) height) / 2.0f, ((float) Math.min(width - CROP_BORDER_WIDTH, height - CROP_BORDER_WIDTH)) / 2.0f, paint);
|
||||
Bitmap croppedImage = cropImageCircle(image, cropWidth, cropHeight);
|
||||
canvas.drawBitmap(croppedImage, ((float) (width - cropWidth)) / 2.0f, ((float) (height - cropHeight)) / 2.0f, new Paint(Paint.ANTI_ALIAS_FLAG));
|
||||
return createBitmap;
|
||||
}
|
||||
|
||||
private Bitmap cropImageCircle(Bitmap srcImage, int width, int height) {
|
||||
Bitmap resultImage = Bitmap.createBitmap(width, height, srcImage.getConfig());
|
||||
Canvas canvas = new Canvas(resultImage);
|
||||
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
canvas.drawCircle(((float) width) / 2.0f, ((float) height) / 2.0f, ((float) Math.min(width, height)) / 2.0f, paint);
|
||||
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
|
||||
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
|
||||
canvas.drawBitmap(srcImage, (float) (this.deviceInfo.startPointX - PIXELS_TO_CROP), (float) (this.deviceInfo.startPointY - PIXELS_TO_CROP), paint);
|
||||
return resultImage;
|
||||
}
|
||||
|
||||
private Bitmap prepareCroppedImageRounded(Bitmap image) {
|
||||
//TODO: implement crop for device with rounded corners
|
||||
return image;
|
||||
}
|
||||
|
||||
private Bitmap prepareCroppedImage(Bitmap bitmap) {
|
||||
if (bitmap == null)
|
||||
return null;
|
||||
if (this.deviceInfo.watchType == 1) {
|
||||
return prepareCroppedImageCircle(bitmap);
|
||||
} else if (this.deviceInfo.watchType == 2) {
|
||||
return prepareCroppedImageRounded(bitmap);
|
||||
}
|
||||
LOG.info("HuaweiP2PScreenshotService unknown watchType: {}", this.deviceInfo.watchType);
|
||||
// I don't know what to do here. So save image as is.
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private boolean saveBitmapOld(String filename, Bitmap bitmap) {
|
||||
LOG.info("HuaweiP2PScreenshotService saveBitmapOld: {}", filename);
|
||||
File targetFile;
|
||||
try {
|
||||
targetFile = new File(FileUtils.getExternalFilesDir() + File.separator + filename);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Could not open Screenshot file to write to", e);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(targetFile);
|
||||
if (!bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream)) {
|
||||
fileOutputStream.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
fileOutputStream.close();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error save bitmap", e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean saveMediaStore(String filename, Bitmap bitmap) {
|
||||
LOG.info("HuaweiP2PScreenshotService saveMediaStore: {}", filename);
|
||||
String relativePath = Environment.DIRECTORY_PICTURES + File.separator + "Screenshots";
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(MediaStore.Images.ImageColumns.RELATIVE_PATH, relativePath);
|
||||
contentValues.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, filename);
|
||||
contentValues.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png");
|
||||
contentValues.put(MediaStore.Images.ImageColumns.IS_PENDING, 1);
|
||||
ContentResolver contentResolver = GBApplication.getContext().getContentResolver();
|
||||
Uri uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
|
||||
|
||||
if (uri == null) {
|
||||
contentValues.clear();
|
||||
contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
OutputStream stream = contentResolver.openOutputStream(uri);
|
||||
if (stream != null && bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream)) {
|
||||
contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0);
|
||||
contentResolver.update(uri, contentValues, null, null);
|
||||
stream.close();
|
||||
return true;
|
||||
}
|
||||
if (stream != null) {
|
||||
stream.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error save screenshot", e);
|
||||
}
|
||||
|
||||
contentValues.clear();
|
||||
contentValues.put(MediaStore.Images.ImageColumns.IS_PENDING, 0);
|
||||
contentResolver.update(uri, contentValues, null, null);
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean saveBitmap(String filename, Bitmap bitmap) {
|
||||
if (Build.VERSION.SDK_INT < 29)
|
||||
return saveBitmapOld(filename, bitmap);
|
||||
return saveMediaStore(filename, bitmap);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handleFile(String filename, byte[] data) {
|
||||
LOG.info("HuaweiP2PScreenshotService handleFile: {}", filename);
|
||||
if (data == null) {
|
||||
LOG.error("HuaweiP2PScreenshotService empty file data");
|
||||
sendCommand(createDownloadResponse(filename, 2).getBytes(StandardCharsets.UTF_8), null);
|
||||
return;
|
||||
}
|
||||
if (this.deviceInfo == null) {
|
||||
LOG.error("HuaweiP2PScreenshotService no device config");
|
||||
sendCommand(createDownloadResponse(filename, 2).getBytes(StandardCharsets.UTF_8), null);
|
||||
return;
|
||||
}
|
||||
|
||||
Bitmap image = null;
|
||||
if (this.deviceInfo.compressionAlgorithm == 1) {
|
||||
image = BitmapFactory.decodeByteArray(data, 0, data.length);
|
||||
}
|
||||
|
||||
if (this.deviceInfo.cutout == 1) {
|
||||
image = this.prepareCroppedImage(image);
|
||||
}
|
||||
if (image == null) {
|
||||
LOG.error("HuaweiP2PScreenshotService no image");
|
||||
sendCommand(createDownloadResponse(filename, 2).getBytes(StandardCharsets.UTF_8), null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (saveBitmap(filename, image)) {
|
||||
sendCommand(createDownloadResponse(filename, 1).getBytes(StandardCharsets.UTF_8), null);
|
||||
} else {
|
||||
LOG.error("HuaweiP2PScreenshotService error to save image");
|
||||
sendCommand(createDownloadResponse(filename, 2).getBytes(StandardCharsets.UTF_8), null);
|
||||
}
|
||||
}
|
||||
|
||||
public static HuaweiP2PScreenshotService getRegisteredInstance(HuaweiP2PManager manager) {
|
||||
return (HuaweiP2PScreenshotService) manager.getRegisteredService(HuaweiP2PScreenshotService.MODULE);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiP2PManager;
|
||||
|
||||
public class HuaweiP2PWakeAppScreenshot implements HuaweiP2PManager.HuaweiWakeApp {
|
||||
@Override
|
||||
public boolean onWakeApp(HuaweiP2PManager manager, Uri uri) {
|
||||
if (HuaweiP2PScreenshotService.getRegisteredInstance(manager) == null) {
|
||||
new HuaweiP2PScreenshotService(manager).register();
|
||||
}
|
||||
|
||||
HuaweiP2PScreenshotService screenshotService = HuaweiP2PScreenshotService.getRegisteredInstance(manager);
|
||||
|
||||
screenshotService.sendNegotiateConfig();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -27,8 +27,9 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupport
|
||||
public class GetFileDownloadCompleteRequest extends Request {
|
||||
|
||||
private final HuaweiFileDownloadManager.FileRequest request;
|
||||
private final byte status;
|
||||
|
||||
public GetFileDownloadCompleteRequest(HuaweiSupportProvider support, HuaweiFileDownloadManager.FileRequest request) {
|
||||
public GetFileDownloadCompleteRequest(HuaweiSupportProvider support, HuaweiFileDownloadManager.FileRequest request, byte status) {
|
||||
super(support);
|
||||
if (request.isNewSync()) {
|
||||
this.serviceId = FileDownloadService2C.id;
|
||||
@ -38,13 +39,14 @@ public class GetFileDownloadCompleteRequest extends Request {
|
||||
this.commandId = FileDownloadService0A.FileDownloadCompleteRequest.id;
|
||||
}
|
||||
this.request = request;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||
try {
|
||||
if (request.isNewSync())
|
||||
return new FileDownloadService2C.FileDownloadCompleteRequest(paramsProvider, this.request.getFileId()).serialize();
|
||||
return new FileDownloadService2C.FileDownloadCompleteRequest(paramsProvider, this.request.getFileId(), status).serialize();
|
||||
else
|
||||
return new FileDownloadService0A.FileDownloadCompleteRequest(paramsProvider).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
|
@ -0,0 +1,45 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileDownloadService2C;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiFileDownloadManager;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class GetFileHashRequest extends Request {
|
||||
private final HuaweiFileDownloadManager.FileRequest request;
|
||||
|
||||
public boolean newSync;
|
||||
public byte fileId;
|
||||
public byte[] fileHash;
|
||||
|
||||
|
||||
public GetFileHashRequest(HuaweiSupportProvider support, HuaweiFileDownloadManager.FileRequest request) {
|
||||
super(support);
|
||||
this.serviceId = FileDownloadService2C.id;
|
||||
this.commandId = FileDownloadService2C.FileRequestHash.id;
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||
try {
|
||||
return new FileDownloadService2C.FileRequestHash.Request(paramsProvider, this.request.getFileId()).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processResponse() throws ResponseParseException {
|
||||
if (this.receivedPacket instanceof FileDownloadService2C.FileRequestHash.Response) {
|
||||
this.newSync = true;
|
||||
FileDownloadService2C.FileRequestHash.Response packet = (FileDownloadService2C.FileRequestHash.Response) this.receivedPacket;
|
||||
this.fileId = packet.fileId;
|
||||
this.fileHash = packet.fileHash;
|
||||
} else {
|
||||
throw new ResponseTypeMismatchException(this.receivedPacket, FileDownloadService2C.FileInfo.Response.class);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileDownloadService2C;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiFileDownloadManager;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class GetFileIncomingAck extends Request {
|
||||
private final HuaweiFileDownloadManager.FileRequest request;
|
||||
private final byte status;
|
||||
|
||||
public GetFileIncomingAck(HuaweiSupportProvider support, HuaweiFileDownloadManager.FileRequest request, byte status) {
|
||||
super(support);
|
||||
this.serviceId = FileDownloadService2C.id;
|
||||
this.commandId = FileDownloadService2C.IncomingInitRequest.id;
|
||||
this.request = request;
|
||||
this.status = status;
|
||||
|
||||
this.addToResponse = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||
try {
|
||||
return new FileDownloadService2C.IncomingInitRequest.Request(this.paramsProvider, this.request.getFilename(), this.request.getInFileType(), this.request.getFileId(), this.request.getFileSize(), this.request.getSrcPackage(), this.request.getDstPackage(), this.request.getSrcFingerprint(), this.request.getDstFingerprint(), this.status).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -54,7 +54,7 @@ public class GetSupportedCommandsRequest extends Request {
|
||||
DeviceConfig.SupportedCommands.Request commandsRequest = new DeviceConfig.SupportedCommands.Request(paramsProvider);
|
||||
byte nextService = activatedServices.remove(0);
|
||||
boolean fits = commandsRequest.addCommandsForService(nextService, this.commandsPerService.get((int) nextService));
|
||||
while (fits && activatedServices.size() > 0) {
|
||||
while (fits && !activatedServices.isEmpty()) {
|
||||
nextService = activatedServices.remove(0);
|
||||
fits = commandsRequest.addCommandsForService(nextService, this.commandsPerService.get((int) nextService));
|
||||
}
|
||||
@ -88,18 +88,12 @@ public class GetSupportedCommandsRequest extends Request {
|
||||
);
|
||||
}
|
||||
|
||||
if (activatedServices.size() > 0) {
|
||||
if (!activatedServices.isEmpty()) {
|
||||
GetSupportedCommandsRequest nextRequest = new GetSupportedCommandsRequest(supportProvider, activatedServices);
|
||||
this.nextRequest(nextRequest);
|
||||
} else {
|
||||
supportProvider.getHuaweiCoordinator().printCommandsPerService();
|
||||
if (supportProvider.getHuaweiCoordinator().supportsExpandCapability()) {
|
||||
GetExpandCapabilityRequest nextRequest = new GetExpandCapabilityRequest(supportProvider);
|
||||
nextRequest.setFinalizeReq(dynamicServicesReq);
|
||||
this.nextRequest(nextRequest);
|
||||
} else {
|
||||
dynamicServicesReq.call();
|
||||
}
|
||||
dynamicServicesReq.call();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ public class GetSupportedServicesRequest extends Request {
|
||||
|
||||
byte[] supportedServices = ((DeviceConfig.SupportedServices.Response) receivedPacket).supportedServices;
|
||||
List<Byte> activatedServices = new ArrayList<>();
|
||||
activatedServices.add((byte) 0x01); // device always support 1 service. add it
|
||||
for (int i = 0; i < supportedServices.length; i++) {
|
||||
if (supportedServices[i] == 1) {
|
||||
activatedServices.add(knownSupportedServices[i]);
|
||||
|
@ -0,0 +1,39 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.DeviceConfig;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class SendGetDefaultSwitch extends Request {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SendGetDefaultSwitch.class);
|
||||
|
||||
public SendGetDefaultSwitch(HuaweiSupportProvider support) {
|
||||
super(support);
|
||||
this.serviceId = DeviceConfig.id;
|
||||
this.commandId = DeviceConfig.GetDefaultSwitch.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requestSupported() {
|
||||
return supportProvider.getHuaweiCoordinator().supportDefaultSwitch();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws Request.RequestCreationException {
|
||||
try {
|
||||
return new DeviceConfig.GetDefaultSwitch.Request(paramsProvider).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new Request.RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processResponse() throws Request.ResponseParseException {
|
||||
LOG.debug("handle GetDefaultSwitch");
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.DeviceConfig;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class SendReverseCapabilitiesRequest extends Request {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SendReverseCapabilitiesRequest.class);
|
||||
|
||||
public SendReverseCapabilitiesRequest(HuaweiSupportProvider support) {
|
||||
super(support);
|
||||
this.serviceId = DeviceConfig.id;
|
||||
this.commandId = DeviceConfig.ReverseCapabilities.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requestSupported() {
|
||||
return supportProvider.getHuaweiCoordinator().supportsReverseCapabilities();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||
DeviceConfig.ReverseCapabilities.Request reverseCapabilitiesRequest = new DeviceConfig.ReverseCapabilities.Request(paramsProvider);
|
||||
try {
|
||||
return reverseCapabilitiesRequest.serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processResponse() throws ResponseParseException {
|
||||
LOG.debug("handle ReverseCapabilities");
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.DeviceConfig.
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class SendSetUpDeviceStatusRequest extends Request {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SetUpDeviceStatusRequest.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SendSetUpDeviceStatusRequest.class);
|
||||
|
||||
public SendSetUpDeviceStatusRequest(HuaweiSupportProvider support) {
|
||||
super(support);
|
||||
|
Loading…
x
Reference in New Issue
Block a user