diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiNotificationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiNotificationService.java index 7fbef5bf6..c9ec83a46 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiNotificationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiNotificationService.java @@ -16,16 +16,18 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.services; +import android.Manifest; +import android.content.pm.PackageManager; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import nodomain.freeyourgadget.gadgetbridge.BuildConfig; -import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences; +import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl; import nodomain.freeyourgadget.gadgetbridge.model.CallSpec; import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; @@ -42,8 +44,10 @@ public class XiaomiNotificationService extends AbstractXiaomiService { public static final int COMMAND_TYPE = 7; public static final int CMD_NOTIFICATION_SEND = 0; + public static final int CMD_CALL_REJECT = 2; + public static final int CMD_CALL_IGNORE = 5; public static final int CMD_CANNED_MESSAGES_GET = 9; - public static final int CMD_CANNED_MESSAGES_SET = 12; + public static final int CMD_CANNED_MESSAGES_SET = 12; // also canned message reply public XiaomiNotificationService(final XiaomiSupport support) { super(support); @@ -56,10 +60,22 @@ public class XiaomiNotificationService extends AbstractXiaomiService { @Override public void handleCommand(final XiaomiProto.Command cmd) { + final GBDeviceEventCallControl deviceEvtCallControl = new GBDeviceEventCallControl(); + switch (cmd.getSubtype()) { + case CMD_CALL_REJECT: + LOG.debug("Reject call"); + deviceEvtCallControl.event = GBDeviceEventCallControl.Event.REJECT; + getSupport().evaluateGBDeviceEvent(deviceEvtCallControl); + return; + case CMD_CALL_IGNORE: + LOG.debug("Ignore call"); + deviceEvtCallControl.event = GBDeviceEventCallControl.Event.IGNORE; + getSupport().evaluateGBDeviceEvent(deviceEvtCallControl); + return; case CMD_CANNED_MESSAGES_GET: handleCannedMessages(cmd.getNotification().getCannedMessages()); - break; + return; } // TODO @@ -68,14 +84,9 @@ public class XiaomiNotificationService extends AbstractXiaomiService { } public void onNotification(final NotificationSpec notificationSpec) { - // TODO this is not working - if (true) { - LOG.warn("Notifications disabled, they're not working"); - return; - } - final XiaomiProto.Notification3.Builder notification3 = XiaomiProto.Notification3.newBuilder() .setId(notificationSpec.getId()) + .setUnknown4("") // ? .setTimestamp(TIMESTAMP_SDF.format(new Date(notificationSpec.when))); if (notificationSpec.sourceAppId != null) { @@ -97,14 +108,15 @@ public class XiaomiNotificationService extends AbstractXiaomiService { notification3.setAppName(notificationSpec.sourceName); } - // TODO what is this? - final String unknown12 = String.format( - Locale.ROOT, - "0|%s|%d|null|12345", - notification3.getPackage(), - notification3.getId() // i think this needs to be converted to unsigned - ); - notification3.setUnknown12(unknown12); + // TODO Open on phone + //final String unknown12 = String.format( + // Locale.ROOT, + // "0|%s|%d|null|12345", + // notification3.getPackage(), + // notification3.getId() // i think this needs to be converted to unsigned + //); + //notification3.setUnknown12(unknown12); + //notification3.setOpenOnPhone(1); final XiaomiProto.Notification2 notification2 = XiaomiProto.Notification2.newBuilder() .setNotification3(notification3) @@ -129,7 +141,50 @@ public class XiaomiNotificationService extends AbstractXiaomiService { } public void onSetCallState(final CallSpec callSpec) { - // TODO + // TODO handle callSpec.command + if (callSpec.command != CallSpec.CALL_INCOMING) { + return; + } + + final XiaomiProto.Notification3.Builder notification3 = XiaomiProto.Notification3.newBuilder() + .setId(12345) // ? + .setUnknown4("") // ? + .setIsCall(true) + .setRepliesAllowed(canSendSms()) + .setTimestamp(TIMESTAMP_SDF.format(new Date())); + + notification3.setPackage(BuildConfig.APPLICATION_ID); + notification3.setAppName("Phone"); + + if (callSpec.name != null) { + notification3.setTitle(callSpec.name); + } else { + notification3.setTitle("?"); + } + if (callSpec.number != null) { + notification3.setBody(callSpec.number); + } else { + notification3.setBody("?"); + } + + // TODO unknown caller i18n + + final XiaomiProto.Notification2 notification2 = XiaomiProto.Notification2.newBuilder() + .setNotification3(notification3) + .build(); + + final XiaomiProto.Notification notification = XiaomiProto.Notification.newBuilder() + .setNotification2(notification2) + .build(); + + getSupport().sendCommand( + "send call", + XiaomiProto.Command.newBuilder() + .setType(COMMAND_TYPE) + .setSubtype(CMD_NOTIFICATION_SEND) + .setNotification(notification) + .build() + ); } public void onSetCannedMessages(final CannedMessagesSpec cannedMessagesSpec) { @@ -177,4 +232,12 @@ public class XiaomiNotificationService extends AbstractXiaomiService { //gbDeviceEventUpdatePreferences.withPreference("canned_reply_" + i, message); //getSupport().evaluateGBDeviceEvent(gbDeviceEventUpdatePreferences); } + + public boolean canSendSms() { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { + return getSupport().getContext().checkSelfPermission(Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED; + } else { + return true; + } + } } diff --git a/app/src/main/proto/xiaomi.proto b/app/src/main/proto/xiaomi.proto index 97df3c54d..b9f5bd2f1 100644 --- a/app/src/main/proto/xiaomi.proto +++ b/app/src/main/proto/xiaomi.proto @@ -442,7 +442,7 @@ message MediaKey { message Notification { optional Notification2 notification2 = 3; - optional Notification4 notification4 = 4; + optional NotificationDismiss notification4 = 4; optional uint32 unknown8 = 8; // 1 on canned replies request? // 7, 9 get | 7, 12 set @@ -457,18 +457,24 @@ message Notification3 { optional string package = 1; optional string appName = 2; optional string title = 3; - optional string timestamp = 6; optional string unknown4 = 4; optional string body = 5; + optional string timestamp = 6; optional uint32 id = 7; - optional string unknown8 = 8; - optional string unknown11 = 11; - optional string unknown12 = 12; - optional uint32 hasReply = 13; + optional bool isCall = 8; + optional bool repliesAllowed = 11; // only for calls? + optional string unknown12 = 12; // "0|||null|12345" + optional uint32 openOnPhone = 13; // 1 to show "Open on phone", needs unknown12 } -message Notification4 { - optional Notification5 notification5 = 1; +message NotificationDismiss { + optional NotificationId notificationId = 1; +} + +message NotificationId { + optional uint32 id = 1; + optional string package = 2; // truncated + optional string unknown4 = 4; // "" } message CannedMessages { @@ -477,12 +483,6 @@ message CannedMessages { optional uint32 maxReplies = 3; } -message Notification5 { - optional uint32 id = 1; - optional string package = 2; - optional string unknown4 = 4; -} - // // Weather //