1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-04 17:27:24 +01:00

added call notification support (doesnt work on all phones)

This commit is contained in:
Daniel Dakhno 2020-02-16 01:17:45 +01:00
parent 17ade7e591
commit f9a4c1ad35
6 changed files with 57 additions and 59 deletions

View File

@ -1,18 +1,33 @@
package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid; package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid;
import android.util.Log;
import java.io.Serializable; import java.io.Serializable;
import java.nio.ByteBuffer;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.PlayNotificationRequest; import java.nio.ByteOrder;
import java.util.zip.CRC32;
public class NotificationHRConfiguration implements Serializable { public class NotificationHRConfiguration implements Serializable {
private String packageName; private String packageName;
private long id = -1; private long id = -1;
private byte[] packageCrc;
public NotificationHRConfiguration(String packageName, long id) { public NotificationHRConfiguration(String packageName, long id) {
this.packageName = packageName; this.packageName = packageName;
this.id = id; this.id = id;
CRC32 crc = new CRC32();
crc.update(packageName.getBytes());
this.packageCrc = ByteBuffer
.allocate(4)
.order(ByteOrder.LITTLE_ENDIAN)
.putInt((int) crc.getValue())
.array();
}
public NotificationHRConfiguration(String packageName, byte[] packageCrc, long id) {
this.id = id;
this.packageCrc = packageCrc;
this.packageName = packageName;
} }
public String getPackageName() { public String getPackageName() {
@ -22,4 +37,8 @@ public class NotificationHRConfiguration implements Serializable {
public long getId() { public long getId() {
return id; return id;
} }
public byte[] getPackageCrc() {
return packageCrc;
}
} }

View File

@ -26,6 +26,7 @@ import java.util.Iterator;
import java.util.TimeZone; import java.util.TimeZone;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl;
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.HRConfigActivity; import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.HRConfigActivity;
@ -37,9 +38,11 @@ import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FossilRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.RequestMtuRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.RequestMtuRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.SetDeviceStateRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.SetDeviceStateRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest.TimeConfigItem; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest.TimeConfigItem;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FilePutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayCallNotificationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayCallNotificationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayNotificationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayNotificationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayTextNotificationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayTextNotificationRequest;
@ -99,46 +102,8 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZING)); queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZING));
// icons
loadNotificationConfigurations(); loadNotificationConfigurations();
queueWrite(new NotificationFilterPutHRRequest(this.notificationConfigurations, this)); queueWrite(new NotificationFilterPutHRRequest(this.notificationConfigurations, this));
// queueWrite(new NotificationFilterPutHRRequest(this.notificationConfigurations,this));
/*try {
final String[] appNames = {"instagram", "snapchat", "line", "whatsapp"};
final String[] paths = {
"/storage/emulated/0/Q/images/icInstagram.icon",
"/storage/emulated/0/Q/images/icSnapchat.icon",
"/storage/emulated/0/Q/images/icLine.icon",
"/storage/emulated/0/Q/images/icWhatsapp.icon"
};
NotificationHRConfiguration[] configs = new NotificationHRConfiguration[4];
NotificationImage[] images = new NotificationImage[4];
for(int i = 0; i < 4; i++){
FileInputStream fis = new FileInputStream(paths[i]);
byte[] imageData = new byte[fis.available()];
fis.read(imageData);
fis.close();
configs[i] = new NotificationHRConfiguration(appNames[i], i);
images[i] = new NotificationImage(appNames[i], imageData);
}
queueWrite(new NotificationImagePutRequest(images, this));
queueWrite(new NotificationFilterPutHRRequest(configs, this));
for(String appName : appNames){
queueWrite(new PlayNotificationHRRequest(
appName,
appName.toUpperCase(),
"this is some strange message",
this
));
}
} catch (Exception e) {
e.printStackTrace();
}*/
setVibrationStrength((short) 75); setVibrationStrength((short) 75);
syncSettings(); syncSettings();
@ -165,6 +130,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
private void loadNotificationConfigurations(){ private void loadNotificationConfigurations(){
this.notificationConfigurations = new NotificationHRConfiguration[]{ this.notificationConfigurations = new NotificationHRConfiguration[]{
new NotificationHRConfiguration("generic", 0), new NotificationHRConfiguration("generic", 0),
new NotificationHRConfiguration("call", new byte[]{(byte)0x80, (byte) 0x00, (byte) 0x59, (byte) 0xB7}, 0)
}; };
} }
@ -539,7 +505,9 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
byte requestType = value[1]; byte requestType = value[1];
if (requestType == (byte) 0x05) { if(requestType == (byte) 0x04){
handleCallRequest(value);
}else if (requestType == (byte) 0x05) {
handleMusicRequest(value); handleMusicRequest(value);
} else if (requestType == (byte) 0x01) { } else if (requestType == (byte) 0x01) {
int eventId = value[2]; int eventId = value[2];
@ -608,6 +576,16 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
} }
} }
private void handleCallRequest(byte[] value) {
boolean acceptCall = value[7] == (byte) 0x00;
queueWrite(new PlayCallNotificationRequest("", false, this));
GBDeviceEventCallControl callControlEvent = new GBDeviceEventCallControl();
callControlEvent.event = acceptCall ? GBDeviceEventCallControl.Event.START : GBDeviceEventCallControl.Event.REJECT;
getDeviceSupport().evaluateGBDeviceEvent(callControlEvent);
}
private void handleMusicRequest(byte[] value) { private void handleMusicRequest(byte[] value) {
byte command = value[3]; byte command = value[3];
logger.info("got music command: " + command); logger.info("got music command: " + command);

View File

@ -1,9 +1,14 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification; package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
public class PlayCallNotificationRequest extends PlayNotificationRequest { public class PlayCallNotificationRequest extends PlayNotificationRequest {
public PlayCallNotificationRequest(String number, boolean callStart, FossilWatchAdapter adapter) { public PlayCallNotificationRequest(String number, boolean callStart, FossilWatchAdapter adapter) {
super(callStart ? 1 : 7, callStart ? 8 : 2, "generic", number, "Incoming Call", adapter); super(callStart ? 1 : 7, callStart ? 8 : 2,
ByteBuffer.wrap(new byte[]{(byte) 0x80, (byte) 0x00, (byte) 0x59, (byte) 0xB7}).order(ByteOrder.LITTLE_ENDIAN).getInt(),
number, "Incoming Call", adapter);
} }
} }

View File

@ -26,8 +26,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
public abstract class PlayNotificationRequest extends FilePutRequest { public abstract class PlayNotificationRequest extends FilePutRequest {
static int id = 0;
public PlayNotificationRequest(int notificationType, int flags, String packageName, FossilWatchAdapter adapter) { public PlayNotificationRequest(int notificationType, int flags, String packageName, FossilWatchAdapter adapter) {
super((short) 0x0900, createFile(notificationType, flags, packageName, packageName, packageName), adapter); super((short) 0x0900, createFile(notificationType, flags, packageName, packageName, packageName), adapter);
} }
@ -36,6 +34,9 @@ public abstract class PlayNotificationRequest extends FilePutRequest {
super((short) 0x0900, createFile(notificationType, flags, packageName, sender, message), adapter); super((short) 0x0900, createFile(notificationType, flags, packageName, sender, message), adapter);
} }
public PlayNotificationRequest(int notificationType, int flags, int packageCRC, String sender, String message, FossilWatchAdapter adapter) {
super((short) 0x0900, createFile(notificationType, flags, "whatever", sender, message, packageCRC), adapter);
}
private static byte[] createFile(int notificationType, int flags, String packageName, String sender, String message){ private static byte[] createFile(int notificationType, int flags, String packageName, String sender, String message){
CRC32 crc = new CRC32(); CRC32 crc = new CRC32();
@ -73,7 +74,7 @@ public abstract class PlayNotificationRequest extends FilePutRequest {
mainBuffer.put((byte) senderBytes.length); mainBuffer.put((byte) senderBytes.length);
mainBuffer.put((byte) messageBytes.length); mainBuffer.put((byte) messageBytes.length);
mainBuffer.putInt(id++); // messageId mainBuffer.putInt(0); // messageId
mainBuffer.putInt(packageCrc); mainBuffer.putInt(packageCrc);
mainBuffer.put(titleBytes); mainBuffer.put(titleBytes);
mainBuffer.put(senderBytes); mainBuffer.put(senderBytes);

View File

@ -3,7 +3,6 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fo
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.zip.CRC32;
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationHRConfiguration; import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationHRConfiguration;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
@ -21,20 +20,16 @@ public class NotificationFilterPutHRRequest extends FilePutRequest {
} }
private static byte[] createFile(NotificationHRConfiguration[] configs) { private static byte[] createFile(NotificationHRConfiguration[] configs) {
ByteBuffer buffer = ByteBuffer.allocate(configs.length * 28); int payloadLength = configs.length * 28;
ByteBuffer buffer = ByteBuffer.allocate(payloadLength);
buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.order(ByteOrder.LITTLE_ENDIAN);
for (NotificationHRConfiguration config : configs) { for (NotificationHRConfiguration config : configs) {
buffer.putShort((short) 28); //packet length payloadLength = 26;
CRC32 crc = new CRC32(); buffer.putShort((short) payloadLength); //packet length
crc.update(config.getPackageName().getBytes());
byte[] crcBytes = ByteBuffer byte[] crcBytes = config.getPackageCrc();
.allocate(4)
.order(ByteOrder.LITTLE_ENDIAN)
.putInt((int) crc.getValue())
.array();
// 6 bytes // 6 bytes
buffer.put(PacketID.PACKAGE_NAME_CRC.id) buffer.put(PacketID.PACKAGE_NAME_CRC.id)
@ -44,7 +39,7 @@ public class NotificationFilterPutHRRequest extends FilePutRequest {
// 3 bytes // 3 bytes
buffer.put(PacketID.GROUP_ID.id) buffer.put(PacketID.GROUP_ID.id)
.put((byte) 1) .put((byte) 1)
.put((byte) 2); .put((byte) 0);
// 3 bytes // 3 bytes
buffer.put(PacketID.PRIORITY.id) buffer.put(PacketID.PRIORITY.id)

View File

@ -53,7 +53,7 @@ public class GBCallControlReceiver extends BroadcastReceiver {
telephonyService.answerRingingCall(); telephonyService.answerRingingCall();
} }
} catch (Exception e) { } catch (Exception e) {
LOG.warn("could not start or hangup call"); LOG.warn("could not start or hangup call", e);
} }
break; break;
default: default: