Huawei: call notifications fix

This commit is contained in:
Me7c7
2025-11-25 15:41:56 +02:00
parent 30e2531733
commit 539f2b416a
6 changed files with 127 additions and 48 deletions
@@ -804,6 +804,12 @@ public class HuaweiCoordinator {
return false;
}
public boolean supportsNotificationsStartCall() {
if (supportsExpandCapability())
return supportsExpandCapability(74);
return false;
}
public boolean supportsNotificationsAddIconTimestamp() {
if (supportsExpandCapability())
return supportsExpandCapability(77);
@@ -996,7 +1002,7 @@ public class HuaweiCoordinator {
return (((notificationCapabilities >> 1) & 1) == 0);
}
public boolean supportsOutgoingCall () {
public boolean supportsOutgoingCall() {
return (((notificationCapabilities >> 2) & 1) == 0);
}
@@ -1004,7 +1010,7 @@ public class HuaweiCoordinator {
return supportsNotificationConstraint(NotificationConstraintsType.yellowPagesSupport);
}
public boolean supportsContentSIgn() {
public boolean supportsContentSign() {
return supportsNotificationConstraint(NotificationConstraintsType.contentSignSupport);
}
@@ -1024,7 +1030,7 @@ public class HuaweiCoordinator {
return getNotificationConstraint(NotificationConstraintsType.contentSignFormat);
}
public int getIncomingFormatFormat() {
public int getIncomingNumberFormat() {
return getNotificationConstraint(NotificationConstraintsType.incomingNumberFormat);
}
@@ -20,6 +20,7 @@ import android.text.TextUtils;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTLV;
@@ -36,6 +37,18 @@ public class Notifications {
public static class NotificationActionRequest extends HuaweiPacket {
public static final byte id = 0x01;
public static class TextElement {
public byte textType;
public byte encoding;
public String value;
public TextElement(byte textType, byte encoding, String value) {
this.textType = textType;
this.value = value;
this.encoding = encoding;
}
}
public static class AdditionalParams {
public boolean supportsReply = false;
@@ -76,10 +89,13 @@ public class Notifications {
ParamsProvider paramsProvider,
short msgId,
byte notificationType,
int encoding,
String titleContent,
String senderContent,
String bodyContent,
ArrayList<TextElement> content,
// int encoding,
// String titleContent,
// String senderContent,
// String bodyContent,
// int numberFormat,
// String numberContent,
String sourceAppId,
AdditionalParams addParams
) {
@@ -96,26 +112,15 @@ public class Notifications {
.put(0x03, true); // This used to be vibrate, but doesn't work
HuaweiTLV subTlv = new HuaweiTLV();
if (titleContent != null && !titleContent.isEmpty())
subTlv.put(0x8D, new HuaweiTLV()
.put(0x0E, (byte) TextType.title)
.put(0x0F, (byte) encoding)
.put(0x10, titleContent)
);
if (senderContent != null && !senderContent.isEmpty())
subTlv.put(0x8D, new HuaweiTLV()
.put(0x0E, (byte) TextType.sender)
.put(0x0F, (byte) encoding)
.put(0x10, senderContent)
);
if (bodyContent != null && !bodyContent.isEmpty())
subTlv.put(0x8D, new HuaweiTLV()
.put(0x0E, (byte) TextType.text)
.put(0x0F, (byte) encoding)
.put(0x10, bodyContent)
);
for(TextElement el: content) {
HuaweiTLV elTlv = new HuaweiTLV()
.put(0x0E, el.textType)
.put(0x0F, el.encoding);
if(el.value != null && !el.value.isEmpty())
elTlv.put(0x10, el.value); // TODO: truncate text by capability.
subTlv.put(0x8D, elTlv);
}
if (subTlv.length() != 0) {
this.tlv.put(0x84, new HuaweiTLV().put(0x8C, subTlv));
@@ -247,8 +252,10 @@ public class Notifications {
public static final byte weChat = 0x03;
public static final byte qq = 0x0B;
public static final byte stopNotification = 0x0C; // To stop showing a (call) notification
public static final byte startCall = 0x0D;
public static final byte missedCall = 0x0E;
public static final byte email = 0x0F;
public static final byte outgoingCall = 0x32;
public static final byte generic = 0x7F;
}
@@ -87,6 +87,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTrueSleepSequen
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiUtil;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.CameraRemote;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.GpsAndTime;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Notifications;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Weather;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Workout;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.ui.HuaweiStressCalibrationFragment;
@@ -1911,7 +1912,7 @@ public class HuaweiSupportProvider {
}
public void onSetCallState(CallSpec callSpec) {
if (callSpec.command == CallSpec.CALL_INCOMING) {
if (callSpec.command == CallSpec.CALL_INCOMING || (callSpec.command == CallSpec.CALL_OUTGOING && getHuaweiCoordinator().supportsOutgoingCall())) {
SendNotificationRequest sendNotificationReq = new SendNotificationRequest(this);
try {
sendNotificationReq.buildNotificationTLVFromCallSpec(callSpec);
@@ -1921,11 +1922,19 @@ public class HuaweiSupportProvider {
}
} else if (
callSpec.command == CallSpec.CALL_ACCEPT ||
callSpec.command == CallSpec.CALL_START ||
callSpec.command == CallSpec.CALL_START) {
byte type = getHuaweiCoordinator().supportsNotificationsStartCall()?Notifications.NotificationType.startCall:Notifications.NotificationType.stopNotification;
StopNotificationRequest stopNotificationRequest = new StopNotificationRequest(this, type);
try {
stopNotificationRequest.doPerform();
} catch (IOException e) {
LOG.error("Failed to send stop call notification", e);
}
}else if (
callSpec.command == CallSpec.CALL_REJECT ||
callSpec.command == CallSpec.CALL_END
) {
StopNotificationRequest stopNotificationRequest = new StopNotificationRequest(this);
StopNotificationRequest stopNotificationRequest = new StopNotificationRequest(this, Notifications.NotificationType.stopNotification);
try {
stopNotificationRequest.doPerform();
} catch (IOException e) {
@@ -21,6 +21,7 @@ import static nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.Huawei
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
@@ -95,29 +96,58 @@ public class SendNotificationRequest extends Request {
params.category = notificationSpec.category;
params.address = notificationSpec.phoneNumber;
ArrayList<Notifications.NotificationActionRequest.TextElement> content = new ArrayList<>();
content.add(
new Notifications.NotificationActionRequest.TextElement(
(byte)Notifications.TextType.title,
(byte)supportProvider.getHuaweiCoordinator().getContentFormat(),
title)
);
content.add(
new Notifications.NotificationActionRequest.TextElement(
(byte) Notifications.TextType.sender,
(byte)supportProvider.getHuaweiCoordinator().getContentFormat(),
notificationSpec.sender)
);
content.add(
new Notifications.NotificationActionRequest.TextElement(
(byte) Notifications.TextType.text,
(byte)supportProvider.getHuaweiCoordinator().getContentFormat(),
body)
);
this.packet = new Notifications.NotificationActionRequest(
paramsProvider,
supportProvider.getNotificationId(),
getNotificationType(notificationSpec.type),
supportProvider.getHuaweiCoordinator().getContentFormat(),
title,
notificationSpec.sender,
body,
content,
notificationSpec.sourceAppId,
params
);
}
public void buildNotificationTLVFromCallSpec(CallSpec callSpec) {
ArrayList<Notifications.NotificationActionRequest.TextElement> content = new ArrayList<>();
content.add(
new Notifications.NotificationActionRequest.TextElement(
(byte) Notifications.TextType.text,
(byte)supportProvider.getHuaweiCoordinator().getContentFormat(),
callSpec.name)
);
if(supportProvider.getHuaweiCoordinator().supportsIncomingNumber()) {
content.add(
new Notifications.NotificationActionRequest.TextElement(
(byte) Notifications.TextType.flight,
(byte) supportProvider.getHuaweiCoordinator().getIncomingNumberFormat(),
callSpec.number)
);
}
final byte notificationType = callSpec.command == CallSpec.CALL_OUTGOING?Notifications.NotificationType.outgoingCall:Notifications.NotificationType.call;
this.packet = new Notifications.NotificationActionRequest(
paramsProvider,
supportProvider.getNotificationId(),
Notifications.NotificationType.call,
supportProvider.getHuaweiCoordinator().getContentFormat(),
callSpec.name,
callSpec.name,
callSpec.name,
notificationType,
content,
null,
null
);
@@ -16,6 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
import java.util.ArrayList;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
@@ -23,24 +24,30 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Notifications
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
public class StopNotificationRequest extends Request {
public StopNotificationRequest(HuaweiSupportProvider support) {
final byte type;
public StopNotificationRequest(HuaweiSupportProvider support, byte type) {
super(support);
this.serviceId = Notifications.id;
this.commandId = Notifications.NotificationActionRequest.id;
this.addToResponse = false;
this.type = type;
}
@Override
protected List<byte[]> createRequest() throws RequestCreationException {
try {
ArrayList<Notifications.NotificationActionRequest.TextElement> content = new ArrayList<>();
content.add(
new Notifications.NotificationActionRequest.TextElement(
(byte) Notifications.TextType.text,
(byte)supportProvider.getHuaweiCoordinator().getContentFormat(),
"")
);
return new Notifications.NotificationActionRequest(
paramsProvider,
supportProvider.getNotificationId(),
Notifications.NotificationType.stopNotification,
supportProvider.getHuaweiCoordinator().getContentFormat(),
null,
null,
null,
type,
content,
null,
null
).serialize();
@@ -21,6 +21,7 @@ import org.junit.Ignore;
import org.junit.Test;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
@@ -98,14 +99,33 @@ public class TestNotifications {
)
.put(0x11, sourceAppId);
ArrayList<Notifications.NotificationActionRequest.TextElement> content = new ArrayList<>();
content.add(
new Notifications.NotificationActionRequest.TextElement(
(byte)Notifications.TextType.title,
(byte)encoding,
titleContent)
);
content.add(
new Notifications.NotificationActionRequest.TextElement(
(byte) Notifications.TextType.sender,
(byte)encoding,
senderContent)
);
content.add(
new Notifications.NotificationActionRequest.TextElement(
(byte) Notifications.TextType.text,
(byte)encoding,
bodyContent)
);
Notifications.NotificationActionRequest request = new Notifications.NotificationActionRequest(
secretsProvider,
notificationId,
notificationType,
encoding,
titleContent,
senderContent,
bodyContent,
content,
sourceAppId,
null
);