From b345e41db07467906d7e690dec9766bbc2dea622 Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Thu, 25 Apr 2024 11:18:51 +0200 Subject: [PATCH] Garmin: fix notification crashes and handle SMS correctly It looks like (some) watches really don't like having an empty list of actions, hence enable the legacy "refuse" action in every case, leaving it empty and inactive. Further display the SMS sender in the notification and enable the correct code path for the reply action to work. --- .../devices/garmin/NotificationsHandler.java | 11 ++-- .../messages/NotificationControlMessage.java | 4 +- .../messages/NotificationUpdateMessage.java | 59 ++++++++++++++++++- 3 files changed, 66 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/NotificationsHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/NotificationsHandler.java index a38a8c029..e4e1a48a3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/NotificationsHandler.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/NotificationsHandler.java @@ -55,7 +55,7 @@ public class NotificationsHandler implements MessageHandler { final byte[] bytes = entry.getKey().getNotificationSpecAttribute(notificationSpec, entry.getValue()); messageWriter.writeShort(bytes.length); messageWriter.writeBytes(bytes); -// LOG.info("ATTRIBUTE:{} value:{} length:{}", entry.getKey(), new String(bytes), bytes.length); +// LOG.info("ATTRIBUTE:{} value:{}/{} length:{}", entry.getKey(), new String(bytes), GB.hexdump(bytes), bytes.length); } @@ -183,7 +183,7 @@ public class NotificationsHandler implements MessageHandler { case REPLY_MESSAGES: deviceEvtNotificationControl.event = GBDeviceEventNotificationControl.Event.REPLY; deviceEvtNotificationControl.reply = message.getActionString(); - if (notificationSpec.type.equals(NotificationType.GENERIC_PHONE)) { + if (notificationSpec.type.equals(NotificationType.GENERIC_PHONE) || notificationSpec.type.equals(NotificationType.GENERIC_SMS)) { deviceEvtNotificationControl.phoneNumber = notificationSpec.phoneNumber; } else { deviceEvtNotificationControl.handle = mNotificationReplyAction.lookup(notificationSpec.getId()); //handle of wearable action is needed @@ -267,7 +267,7 @@ public class NotificationsHandler implements MessageHandler { MESSAGE_SIZE(4), DATE(5), // POSITIVE_ACTION_LABEL(6), //needed only for legacy notification actions - // NEGATIVE_ACTION_LABEL(7), //needed only for legacy notification actions + NEGATIVE_ACTION_LABEL(7), //needed only for legacy notification actions // Garmin extensions // PHONE_NUMBER(126, true), ACTIONS(127, false, true), @@ -312,7 +312,10 @@ public class NotificationsHandler implements MessageHandler { toReturn = NOTIFICATION_DATE_FORMAT.format(new Date(notificationTimestamp)); break; case TITLE: - toReturn = notificationSpec.title == null ? "" : notificationSpec.title; + if (NotificationType.GENERIC_SMS.equals(notificationSpec.type)) + toReturn = notificationSpec.sender == null ? "" : notificationSpec.sender; + else + toReturn = notificationSpec.title == null ? "" : notificationSpec.title; break; case SUBTITLE: toReturn = notificationSpec.subject == null ? "" : notificationSpec.subject; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/messages/NotificationControlMessage.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/messages/NotificationControlMessage.java index 1655200d2..bb9b9a31b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/messages/NotificationControlMessage.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/messages/NotificationControlMessage.java @@ -1,7 +1,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages; import java.util.Collections; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -77,7 +77,7 @@ public class NotificationControlMessage extends GFDIMessage { } private static Map createGetNotificationAttributesCommand(MessageReader reader) { - final Map notificationAttributesMap = new HashMap<>(); + final Map notificationAttributesMap = new LinkedHashMap<>(); while (reader.remaining() > 0) { final int attributeID = reader.readByte(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/messages/NotificationUpdateMessage.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/messages/NotificationUpdateMessage.java index fa245f81e..fa286b7ef 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/messages/NotificationUpdateMessage.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/messages/NotificationUpdateMessage.java @@ -34,17 +34,64 @@ public class NotificationUpdateMessage extends GFDIMessage { writer.writeByte(getCategoryValue(this.notificationType)); writer.writeByte(this.count); writer.writeInt(this.notificationId); - writer.writeByte(this.useLegacyActions ? 0x00 : 0x03); + writer.writeByte(getNotificationPhoneFlags()); return true; } + private int getNotificationPhoneFlags() { + EnumSet flags = EnumSet.noneOf(NotificationPhoneFlags.class); + if (this.hasActions) + flags.add(NotificationPhoneFlags.NEW_ACTIONS); + if (this.useLegacyActions) + flags.add(NotificationPhoneFlags.LEGACY_ACTIONS); + + return (int) EnumUtils.generateBitVector(NotificationPhoneFlags.class, flags); + + } + + //no image + //00 updatetype + // 12 flags + // 00 notif type + // 00 count + // 03000000 + // 02 + + + //image + //00 + // 12 + // 00 + // 00 + // 04000000 + // 06 + + //0F00 + // A913 + // 00 + // 12 + // 0C + // 00 + // 471D2A66 + // 02 + // BC14 + + //0F00 + // A913 + // 00 + // 11 + // 00 + // 00 + // 461D2A66 + // 00 + // 8C00 private int getCategoryFlags(NotificationType notificationType) { EnumSet flags = EnumSet.noneOf(NotificationFlag.class); if (this.hasActions && this.useLegacyActions) { //only needed for legacy actions flags.add(NotificationFlag.ACTION_ACCEPT); - flags.add(NotificationFlag.ACTION_DECLINE); } + flags.add(NotificationFlag.ACTION_DECLINE); switch (notificationType.getGenericType()) { case "generic_phone": @@ -111,5 +158,13 @@ public class NotificationUpdateMessage extends GFDIMessage { LOCATION, ENTERTAINMENT, SMS + + } + + enum NotificationPhoneFlags { + LEGACY_ACTIONS, + NEW_ACTIONS, + HAS_ATTACHMENTS, + ; } }