Fossil Hybrid: added unauthenticated, limited mode

This commit is contained in:
Daniel Dakhno
2020-11-12 03:49:52 +01:00
parent 9fafe3929f
commit 39ed94de87
7 changed files with 143 additions and 80 deletions

View File

@@ -109,7 +109,7 @@ public class FossilWatchAdapter extends WatchAdapter {
getDeviceInfos(); getDeviceInfos();
} }
public short getSupportedFileVersion(FileHandle handle){ public short getSupportedFileVersion(FileHandle handle) {
return this.supportedFileVersions.getSupportedFileVersion(handle); return this.supportedFileVersions.getSupportedFileVersion(handle);
} }
@@ -123,14 +123,14 @@ public class FossilWatchAdapter extends WatchAdapter {
queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZED), false); queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZED), false);
} }
protected void getDeviceInfos(){ protected void getDeviceInfos() {
queueWrite(new GetDeviceInfoRequest(this){ queueWrite(new GetDeviceInfoRequest(this) {
@Override @Override
public void handleDeviceInfos(DeviceInfo[] deviceInfos) { public void handleDeviceInfos(DeviceInfo[] deviceInfos) {
for(DeviceInfo info : deviceInfos){ for (DeviceInfo info : deviceInfos) {
if(info instanceof SupportedFileVersionsInfo){ if (info instanceof SupportedFileVersionsInfo) {
FossilWatchAdapter.this.supportedFileVersions = (SupportedFileVersionsInfo) info; FossilWatchAdapter.this.supportedFileVersions = (SupportedFileVersionsInfo) info;
}else if(info instanceof DeviceSecurityVersionInfo){ } else if (info instanceof DeviceSecurityVersionInfo) {
getDeviceSupport().getDevice().addDeviceInfo(new GenericItem("DEVICE_SECURITY_VERSION", info.toString())); getDeviceSupport().getDevice().addDeviceInfo(new GenericItem("DEVICE_SECURITY_VERSION", info.toString()));
} }
} }
@@ -139,7 +139,7 @@ public class FossilWatchAdapter extends WatchAdapter {
}); });
} }
private void syncButtonSettings(){ private void syncButtonSettings() {
String buttonConfig = getDeviceSpecificPreferences().getString(CONFIG_ITEM_BUTTONS, null); String buttonConfig = getDeviceSpecificPreferences().getString(CONFIG_ITEM_BUTTONS, null);
getDeviceSupport().getDevice().addDeviceInfo(new GenericItem(ITEM_BUTTONS, buttonConfig)); getDeviceSupport().getDevice().addDeviceInfo(new GenericItem(ITEM_BUTTONS, buttonConfig));
overwriteButtons(buttonConfig); overwriteButtons(buttonConfig);
@@ -147,8 +147,8 @@ public class FossilWatchAdapter extends WatchAdapter {
@Override @Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if(status != BluetoothGatt.GATT_SUCCESS){ if (status != BluetoothGatt.GATT_SUCCESS) {
if(characteristic.getUuid().toString().equals("3dda0005-957f-7d4a-34a6-74696673696d")){ if (characteristic.getUuid().toString().equals("3dda0005-957f-7d4a-34a6-74696673696d")) {
GB.log("authentication failed", GB.ERROR, null); GB.log("authentication failed", GB.ERROR, null);
setDeviceState(GBDevice.State.AUTHENTICATION_REQUIRED); setDeviceState(GBDevice.State.AUTHENTICATION_REQUIRED);
requestQueue.clear(); requestQueue.clear();
@@ -163,20 +163,20 @@ public class FossilWatchAdapter extends WatchAdapter {
@Override @Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
log("status " + status + " newState: " + newState); log("status " + status + " newState: " + newState);
if(newState != BluetoothGatt.STATE_CONNECTED){ if (newState != BluetoothGatt.STATE_CONNECTED) {
log("status " + newState + " clearing queue..."); log("status " + newState + " clearing queue...");
requestQueue.clear(); requestQueue.clear();
fossilRequest = null; fossilRequest = null;
} }
} }
protected SharedPreferences getDeviceSpecificPreferences(){ protected SharedPreferences getDeviceSpecificPreferences() {
return GBApplication.getDeviceSpecificSharedPrefs( return GBApplication.getDeviceSpecificSharedPrefs(
getDeviceSupport().getDevice().getAddress() getDeviceSupport().getDevice().getAddress()
); );
} }
private void syncConfiguration(){ private void syncConfiguration() {
SharedPreferences preferences = getDeviceSpecificPreferences(); SharedPreferences preferences = getDeviceSpecificPreferences();
int stepGoal = preferences.getInt(CONFIG_ITEM_STEP_GOAL, 1000000); int stepGoal = preferences.getInt(CONFIG_ITEM_STEP_GOAL, 1000000);
@@ -225,7 +225,7 @@ public class FossilWatchAdapter extends WatchAdapter {
); );
} }
protected ConfigurationPutRequest.TimeConfigItem generateTimeConfigItemNow(){ protected ConfigurationPutRequest.TimeConfigItem generateTimeConfigItemNow() {
long millis = System.currentTimeMillis(); long millis = System.currentTimeMillis();
TimeZone zone = new GregorianCalendar().getTimeZone(); TimeZone zone = new GregorianCalendar().getTimeZone();
@@ -239,7 +239,7 @@ public class FossilWatchAdapter extends WatchAdapter {
@Override @Override
public void overwriteButtons(String jsonConfigString) { public void overwriteButtons(String jsonConfigString) {
try { try {
if(jsonConfigString == null) return; if (jsonConfigString == null) return;
getDeviceSpecificPreferences() getDeviceSpecificPreferences()
.edit() .edit()
.putString(CONFIG_ITEM_BUTTONS, jsonConfigString) .putString(CONFIG_ITEM_BUTTONS, jsonConfigString)
@@ -398,12 +398,12 @@ public class FossilWatchAdapter extends WatchAdapter {
.putInt(CONFIG_ITEM_TIMEZONE_OFFSET, offset) .putInt(CONFIG_ITEM_TIMEZONE_OFFSET, offset)
.apply(); .apply();
queueWrite(new ConfigurationPutRequest(new ConfigurationPutRequest.TimezoneOffsetConfigItem(offset), this){ queueWrite(new ConfigurationPutRequest(new ConfigurationPutRequest.TimezoneOffsetConfigItem(offset), this) {
@Override @Override
public void onFilePut(boolean success) { public void onFilePut(boolean success) {
super.onFilePut(success); super.onFilePut(success);
if(success) GB.toast("successfully updated timezone", Toast.LENGTH_SHORT, GB.INFO); if (success) GB.toast("successfully updated timezone", Toast.LENGTH_SHORT, GB.INFO);
else GB.toast("error updating timezone", Toast.LENGTH_SHORT, GB.ERROR); else GB.toast("error updating timezone", Toast.LENGTH_SHORT, GB.ERROR);
} }
}); });
@@ -458,11 +458,11 @@ public class FossilWatchAdapter extends WatchAdapter {
@Override @Override
public void onSetAlarms(ArrayList<? extends Alarm> alarms) { public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
// throw new RuntimeException("noope"); // throw new RuntimeException("noope");
ArrayList<nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.alarm.Alarm> activeAlarms = new ArrayList<>(); ArrayList<nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.alarm.Alarm> activeAlarms = new ArrayList<>();
for (Alarm alarm : alarms){ for (Alarm alarm : alarms) {
if(!alarm.getEnabled()) continue; if (!alarm.getEnabled()) continue;
if(alarm.getRepetition() == 0){ if (alarm.getRepetition() == 0) {
activeAlarms.add(new nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.alarm.Alarm( activeAlarms.add(new nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.alarm.Alarm(
(byte) alarm.getMinute(), (byte) alarm.getMinute(),
(byte) alarm.getHour(), (byte) alarm.getHour(),
@@ -481,12 +481,12 @@ public class FossilWatchAdapter extends WatchAdapter {
alarm.getDescription() alarm.getDescription()
)); ));
} }
queueWrite(new AlarmsSetRequest(activeAlarms.toArray(new nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.alarm.Alarm[0]), this){ queueWrite(new AlarmsSetRequest(activeAlarms.toArray(new nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.alarm.Alarm[0]), this) {
@Override @Override
public void onFilePut(boolean success) { public void onFilePut(boolean success) {
super.onFilePut(success); super.onFilePut(success);
if(success) GB.toast("successfully set alarms", Toast.LENGTH_SHORT, GB.INFO); if (success) GB.toast("successfully set alarms", Toast.LENGTH_SHORT, GB.INFO);
else GB.toast("error setting alarms", Toast.LENGTH_SHORT, GB.INFO); else GB.toast("error setting alarms", Toast.LENGTH_SHORT, GB.INFO);
} }
}); });
} }
@@ -525,15 +525,15 @@ public class FossilWatchAdapter extends WatchAdapter {
fossilRequest.handleResponse(characteristic); fossilRequest.handleResponse(characteristic);
requestFinished = fossilRequest.isFinished(); requestFinished = fossilRequest.isFinished();
} catch (RuntimeException e) { } catch (RuntimeException e) {
if(characteristic.getUuid().toString().equals("3dda0005-957f-7d4a-34a6-74696673696d")){ if (characteristic.getUuid().toString().equals("3dda0005-957f-7d4a-34a6-74696673696d")) {
GB.log("authentication failed", GB.ERROR, null); GB.log("authentication failed", GB.ERROR, null);
setDeviceState(GBDevice.State.AUTHENTICATION_REQUIRED); // setDeviceState(GBDevice.State.AUTHENTICATION_REQUIRED);
requestQueue.clear(); }else {
GB.log("error", GB.ERROR, e);
getDeviceSupport().notifiyException(fossilRequest.getName(), e);
GB.toast(fossilRequest.getName() + " failed", Toast.LENGTH_SHORT, GB.ERROR);
} }
GB.log("error", GB.ERROR, e);
getDeviceSupport().notifiyException(fossilRequest.getName(), e);
GB.toast(fossilRequest.getName() + " failed", Toast.LENGTH_SHORT, GB.ERROR);
requestFinished = true; requestFinished = true;
} }
@@ -618,8 +618,8 @@ public class FossilWatchAdapter extends WatchAdapter {
int action = value[3]; int action = value[3];
String actionString = "SINGLE"; String actionString = "SINGLE";
if(action == 3) actionString = "DOUBLE"; if (action == 3) actionString = "DOUBLE";
else if(action == 4) actionString = "LONG"; else if (action == 4) actionString = "LONG";
// lastButtonIndex = index; // lastButtonIndex = index;
log(actionString + " button press"); log(actionString + " button press");
@@ -637,7 +637,7 @@ public class FossilWatchAdapter extends WatchAdapter {
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status); super.onMtuChanged(gatt, mtu, status);
if(this.MTU == mtu){ if (this.MTU == mtu) {
log("MTU changed, same value tho"); log("MTU changed, same value tho");
return; return;
} }
@@ -655,7 +655,7 @@ public class FossilWatchAdapter extends WatchAdapter {
public void queueWrite(RequestMtuRequest request, boolean priorise) { public void queueWrite(RequestMtuRequest request, boolean priorise) {
log("is connected: " + getDeviceSupport().isConnected()); log("is connected: " + getDeviceSupport().isConnected());
if(!getDeviceSupport().isConnected()){ if (!getDeviceSupport().isConnected()) {
log("dropping requetst " + request.getName()); log("dropping requetst " + request.getName());
return; return;
} }
@@ -687,14 +687,14 @@ public class FossilWatchAdapter extends WatchAdapter {
queueNextRequest(); queueNextRequest();
} }
private void setDeviceState(GBDevice.State state){ private void setDeviceState(GBDevice.State state) {
getDeviceSupport().getDevice().setState(state); getDeviceSupport().getDevice().setState(state);
getDeviceSupport().getDevice().sendDeviceUpdateIntent(getContext()); getDeviceSupport().getDevice().sendDeviceUpdateIntent(getContext());
} }
public void queueWrite(FossilRequest request, boolean priorise) { public void queueWrite(FossilRequest request, boolean priorise) {
log("is connected: " + getDeviceSupport().isConnected()); log("is connected: " + getDeviceSupport().isConnected());
if(!getDeviceSupport().isConnected()){ if (!getDeviceSupport().isConnected()) {
log("dropping requetst " + request.getName()); log("dropping requetst " + request.getName());
return; return;
} }
@@ -711,7 +711,7 @@ public class FossilWatchAdapter extends WatchAdapter {
this.fossilRequest = request; this.fossilRequest = request;
new TransactionBuilder(request.getClass().getSimpleName()).write(getDeviceSupport().getCharacteristic(request.getRequestUUID()), request.getRequestData()).queue(getDeviceSupport().getQueue()); new TransactionBuilder(request.getClass().getSimpleName()).write(getDeviceSupport().getCharacteristic(request.getRequestUUID()), request.getRequestData()).queue(getDeviceSupport().getQueue());
if(request.isFinished()){ if (request.isFinished()) {
this.fossilRequest = null; this.fossilRequest = null;
queueNextRequest(); queueNextRequest();
} }
@@ -719,7 +719,7 @@ public class FossilWatchAdapter extends WatchAdapter {
public void queueWrite(Request request, boolean priorise) { public void queueWrite(Request request, boolean priorise) {
log("is connected: " + getDeviceSupport().isConnected()); log("is connected: " + getDeviceSupport().isConnected());
if(!getDeviceSupport().isConnected()){ if (!getDeviceSupport().isConnected()) {
log("dropping requetst " + request.getName()); log("dropping requetst " + request.getName());
return; return;
} }
@@ -730,7 +730,7 @@ public class FossilWatchAdapter extends WatchAdapter {
protected void queueWrite(Request request) { protected void queueWrite(Request request) {
log("is connected: " + getDeviceSupport().isConnected()); log("is connected: " + getDeviceSupport().isConnected());
if(!getDeviceSupport().isConnected()){ if (!getDeviceSupport().isConnected()) {
log("dropping requetst " + request.getName()); log("dropping requetst " + request.getName());
return; return;
} }

View File

@@ -66,6 +66,8 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.buttonconfig
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.parser.ActivityEntry; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.parser.ActivityEntry;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.parser.ActivityFileParser; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.parser.ActivityFileParser;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
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.button.ButtonConfigurationGetRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.button.ButtonConfigurationGetRequest;
@@ -85,6 +87,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.AssetFilePutRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.AssetFilePutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedGetRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FilePutRawRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FilePutRawRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedInterface;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FirmwareFilePutRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FirmwareFilePutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImage; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImage;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImageFactory; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImageFactory;
@@ -105,6 +108,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.WidgetsPutRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.WidgetsPutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.AnimationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.AnimationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.FactoryResetRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.FactoryResetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.SetTimeRequest;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs; import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
@@ -139,18 +143,16 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
HashMap<String, Bitmap> appIconCache = new HashMap<>(); HashMap<String, Bitmap> appIconCache = new HashMap<>();
String lastPostedApp = null; String lastPostedApp = null;
enum CONNECTION_MODE {
NOT_INITIALIZED,
AUTHENTICATED,
NOT_AUTHENTICATED
}
CONNECTION_MODE connectionMode = CONNECTION_MODE.NOT_INITIALIZED;
@Override @Override
public void initialize() { public void initialize() {
try {
getSecretKey();
} catch (IllegalAccessException e) {
GB.toast("erro getting key: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e);
new TransactionBuilder("init fail")
.add(new SetDeviceStateAction(getDeviceSupport().getDevice(), GBDevice.State.AUTHENTICATION_REQUIRED, getContext()))
.queue(getDeviceSupport().getQueue());
return;
}
saveRawActivityFiles = getDeviceSpecificPreferences().getBoolean("save_raw_activity_files", false); saveRawActivityFiles = getDeviceSpecificPreferences().getBoolean("save_raw_activity_files", false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@@ -162,23 +164,33 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
@Override @Override
protected void initializeWithSupportedFileVersions() { protected void initializeWithSupportedFileVersions() {
if (getDeviceSupport().getDevice().getFirmwareVersion().contains("prod")) {
GB.toast("Dummy FW, skipping initialization", Toast.LENGTH_LONG, GB.INFO);
queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZED), false);
return;
}
queueWrite(new SetDeviceStateRequest(GBDevice.State.AUTHENTICATING)); queueWrite(new SetDeviceStateRequest(GBDevice.State.AUTHENTICATING));
negotiateSymmetricKey(); negotiateSymmetricKey();
}
private void initializeAfterAuthentication(boolean authenticated){
queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZING)); queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZING));
if(!authenticated) GB.toast("Authentication failed, limited functionality", Toast.LENGTH_LONG, GB.ERROR);
loadNotificationConfigurations(); loadNotificationConfigurations();
queueWrite(new NotificationFilterPutHRRequest(this.notificationConfigurations, this)); queueWrite(new NotificationFilterPutHRRequest(this.notificationConfigurations, this));
setVibrationStrength();
syncSettings(); if(authenticated){
setVibrationStrength();
setTime(); syncSettings();
setTime();
}
overwriteButtons(null); overwriteButtons(null);
loadBackground(); loadBackground();
loadWidgets(); loadWidgets();
// renderWidgets(); // renderWidgets();
@@ -187,6 +199,12 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZED)); queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZED));
} }
private void handleAuthenticationResult(boolean success){
if(this.connectionMode != CONNECTION_MODE.NOT_INITIALIZED) return;
this.connectionMode = success ? CONNECTION_MODE.AUTHENTICATED : CONNECTION_MODE.NOT_AUTHENTICATED;
this.initializeAfterAuthentication(success);
}
private void setVibrationStrength() { private void setVibrationStrength() {
Prefs prefs = new Prefs(getDeviceSpecificPreferences()); Prefs prefs = new Prefs(getDeviceSpecificPreferences());
int vibrationStrengh = prefs.getInt(DeviceSettingsPreferenceConst.PREF_VIBRATION_STRENGH_PERCENTAGE, 2); int vibrationStrengh = prefs.getInt(DeviceSettingsPreferenceConst.PREF_VIBRATION_STRENGH_PERCENTAGE, 2);
@@ -198,8 +216,14 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
@Override @Override
public void setVibrationStrength(short strength) { public void setVibrationStrength(short strength) {
negotiateSymmetricKey(); if(connectionMode == CONNECTION_MODE.NOT_AUTHENTICATED){
queueWrite(new ConfigurationPutRequest(new nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest.VibrationStrengthConfigItem((byte) strength), this)); GB.toast("not available in unauthenticated mode", Toast.LENGTH_LONG, GB.ERROR);
return;
}
queueWrite(
(FileEncryptedInterface) new ConfigurationPutRequest(new nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest.VibrationStrengthConfigItem((byte) strength), this)
);
} }
private void loadNotificationConfigurations() { private void loadNotificationConfigurations() {
@@ -337,7 +361,6 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
} }
private void uploadWidgets() { private void uploadWidgets() {
negotiateSymmetricKey();
ArrayList<Widget> systemWidgets = new ArrayList<>(widgets.size()); ArrayList<Widget> systemWidgets = new ArrayList<>(widgets.size());
for (Widget widget : this.widgets) { for (Widget widget : this.widgets) {
if (!(widget instanceof CustomWidget) && !widget.getWidgetType().isCustom()) if (!(widget instanceof CustomWidget) && !widget.getWidgetType().isCustom())
@@ -514,7 +537,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
} }
} }
private void handleFileDownload(FileHandle handle, byte[] file){ private void handleFileDownload(FileHandle handle, byte[] file) {
Intent resultIntent = new Intent(QHybridSupport.QHYBRID_ACTION_DOWNLOADED_FILE); Intent resultIntent = new Intent(QHybridSupport.QHYBRID_ACTION_DOWNLOADED_FILE);
File outputFile = new File(getContext().getExternalFilesDir("download"), handle.name() + "_" + System.currentTimeMillis() + ".bin"); File outputFile = new File(getContext().getExternalFilesDir("download"), handle.name() + "_" + System.currentTimeMillis() + ".bin");
try { try {
@@ -547,7 +570,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
return; return;
} }
queueWrite(new FilePutRawRequest(handle, fileData, this){ queueWrite(new FilePutRawRequest(handle, fileData, this) {
@Override @Override
public void onFilePut(boolean success) { public void onFilePut(boolean success) {
resultIntent.putExtra("EXTRA_SUCCESS", success); resultIntent.putExtra("EXTRA_SUCCESS", success);
@@ -558,16 +581,15 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
@Override @Override
public void downloadFile(final FileHandle handle, boolean fileIsEncrypted) { public void downloadFile(final FileHandle handle, boolean fileIsEncrypted) {
if(fileIsEncrypted){ if (fileIsEncrypted) {
negotiateSymmetricKey(); queueWrite((FileEncryptedInterface) new FileEncryptedGetRequest(handle, this) {
queueWrite(new FileEncryptedGetRequest(handle, this) {
@Override @Override
public void handleFileData(byte[] fileData) { public void handleFileData(byte[] fileData) {
logger.debug("downloaded encrypted file"); logger.debug("downloaded encrypted file");
handleFileDownload(handle, fileData); handleFileDownload(handle, fileData);
} }
}); });
}else{ } else {
queueWrite(new FileGetRawRequest(handle, this) { queueWrite(new FileGetRawRequest(handle, this) {
@Override @Override
public void handleFileRawData(byte[] fileData) { public void handleFileRawData(byte[] fileData) {
@@ -589,21 +611,43 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
if (renderOnWatch && update) renderWidgets(); if (renderOnWatch && update) renderWidgets();
} }
private void queueWrite(final FileEncryptedInterface request){
try {
queueWrite(new VerifyPrivateKeyRequest(
this.getSecretKey(),
this
){
@Override
protected void handleAuthenticationResult(boolean success) {
if(success){
GB.log("success auth", GB.INFO, null);
queueWrite((FossilRequest) request, true);
}
}
});
} catch (IllegalAccessException e) {
GB.toast("error getting key: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e);
}
}
private void negotiateSymmetricKey() { private void negotiateSymmetricKey() {
try { try {
queueWrite(new VerifyPrivateKeyRequest( queueWrite(new VerifyPrivateKeyRequest(
this.getSecretKey(), this.getSecretKey(),
this this
)); ){
@Override
protected void handleAuthenticationResult(boolean success) {
FossilHRWatchAdapter.this.handleAuthenticationResult(success);
}
});
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
GB.toast("error getting key: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e); GB.toast("error getting key: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e);
getDeviceSupport().getDevice().setState(GBDevice.State.AUTHENTICATION_REQUIRED); this.handleAuthenticationResult(false);
getDeviceSupport().getDevice().sendDeviceUpdateIntent(getContext());
getDeviceSupport().getQueue().clear();
} }
} }
private void toast(final String data){ private void toast(final String data) {
new Handler(Looper.getMainLooper()).post(new Runnable() { new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override @Override
public void run() { public void run() {
@@ -614,10 +658,12 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
@Override @Override
public void setTime() { public void setTime() {
negotiateSymmetricKey(); if(connectionMode == CONNECTION_MODE.NOT_AUTHENTICATED){
GB.toast("not available in unauthenticated mode", Toast.LENGTH_LONG, GB.ERROR);
return;
}
queueWrite( queueWrite(
new ConfigurationPutRequest(this.generateTimeConfigItemNow() ,this), false (FileEncryptedInterface) new ConfigurationPutRequest(this.generateTimeConfigItemNow(), this)
); );
} }
@@ -659,13 +705,17 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
@Override @Override
public void onFetchActivityData() { public void onFetchActivityData() {
if(connectionMode == CONNECTION_MODE.NOT_AUTHENTICATED){
GB.toast("not available in unauthenticated mode", Toast.LENGTH_LONG, GB.ERROR);
return;
}
syncSettings(); syncSettings();
negotiateSymmetricKey();
queueWrite(new FileLookupRequest(FileHandle.ACTIVITY_FILE, this) { queueWrite(new FileLookupRequest(FileHandle.ACTIVITY_FILE, this) {
@Override @Override
public void handleFileLookup(final short fileHandle) { public void handleFileLookup(final short fileHandle) {
queueWrite(new FileEncryptedGetRequest(fileHandle, FossilHRWatchAdapter.this) { queueWrite((FileEncryptedInterface) new FileEncryptedGetRequest(fileHandle, FossilHRWatchAdapter.this) {
@Override @Override
public void handleFileData(byte[] fileData) { public void handleFileData(byte[] fileData) {
try (DBHandler dbHandler = GBApplication.acquireDB()) { try (DBHandler dbHandler = GBApplication.acquireDB()) {
@@ -725,9 +775,12 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
} }
private void syncSettings() { private void syncSettings() {
negotiateSymmetricKey(); if(connectionMode == CONNECTION_MODE.NOT_AUTHENTICATED){
GB.toast("not available in unauthenticated mode", Toast.LENGTH_LONG, GB.ERROR);
return;
}
queueWrite(new ConfigurationGetRequest(this)); queueWrite((FileEncryptedInterface) new ConfigurationGetRequest(this));
} }
@Override @Override
@@ -1010,7 +1063,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
if (authKey != null && !authKey.isEmpty()) { if (authKey != null && !authKey.isEmpty()) {
authKey = authKey.replace(" ", ""); authKey = authKey.replace(" ", "");
authKey = authKey.replace("0x", ""); authKey = authKey.replace("0x", "");
if(authKey.length() != 32){ if (authKey.length() != 32) {
throw new IllegalAccessException("Key should be 16 bytes long as hex string"); throw new IllegalAccessException("Key should be 16 bytes long as hex string");
} }
byte[] srcBytes = GB.hexStringToByteArray(authKey); byte[] srcBytes = GB.hexStringToByteArray(authKey);
@@ -1052,10 +1105,11 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
String firmware = getDeviceSupport().getDevice().getFirmwareVersion(); String firmware = getDeviceSupport().getDevice().getFirmwareVersion();
Matcher matcher = Pattern.compile("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+").matcher(firmware); // DN1.0.2.19r.v5 Matcher matcher = Pattern.compile("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+").matcher(firmware); // DN1.0.2.19r.v5
if(matcher.find()){ if (matcher.find()) {
firmware = matcher.group(0); firmware = matcher.group(0);
Version version = new Version(firmware); Version version = new Version(firmware);
if(version.compareTo(new Version("1.0.2.19")) == -1) singlePressEvent = "single_click"; if (version.compareTo(new Version("1.0.2.19")) == -1)
singlePressEvent = "single_click";
} }
ButtonConfiguration[] buttonConfigurations = new ButtonConfiguration[]{ ButtonConfiguration[] buttonConfigurations = new ButtonConfiguration[]{

View File

@@ -84,6 +84,8 @@ public class VerifyPrivateKeyRequest extends FossilRequest {
} else if (value[1] == 2) { } else if (value[1] == 2) {
ResultCode code = ResultCode.fromCode(value[2]); ResultCode code = ResultCode.fromCode(value[2]);
handleAuthenticationResult(code.inidicatesSuccess());
if (!code.inidicatesSuccess()) throw new RuntimeException("Authentication error: " + code + " (" + value[2] + ")"); if (!code.inidicatesSuccess()) throw new RuntimeException("Authentication error: " + code + " (" + value[2] + ")");
@@ -91,6 +93,8 @@ public class VerifyPrivateKeyRequest extends FossilRequest {
} }
} }
protected void handleAuthenticationResult(boolean success){}
@Override @Override
public boolean isFinished() { public boolean isFinished() {
return isFinished; return isFinished;

View File

@@ -10,10 +10,11 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSuppo
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedInterface;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedLookupAndGetRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedLookupAndGetRequest;
import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class ConfigurationGetRequest extends FileEncryptedLookupAndGetRequest { public class ConfigurationGetRequest extends FileEncryptedLookupAndGetRequest implements FileEncryptedInterface {
public ConfigurationGetRequest(FossilHRWatchAdapter adapter) { public ConfigurationGetRequest(FossilHRWatchAdapter adapter) {
super(FileHandle.CONFIGURATION, adapter); super(FileHandle.CONFIGURATION, adapter);
} }

View File

@@ -42,7 +42,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.CRC32C;
import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
public abstract class FileEncryptedGetRequest extends FossilRequest { public abstract class FileEncryptedGetRequest extends FossilRequest implements FileEncryptedInterface{
private short handle; private short handle;
private FossilHRWatchAdapter adapter; private FossilHRWatchAdapter adapter;

View File

@@ -0,0 +1,4 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file;
public interface FileEncryptedInterface {
}

View File

@@ -36,7 +36,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos
import nodomain.freeyourgadget.gadgetbridge.util.CRC32C; import nodomain.freeyourgadget.gadgetbridge.util.CRC32C;
import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class FileEncryptedPutRequest extends FossilRequest { public class FileEncryptedPutRequest extends FossilRequest implements FileEncryptedInterface {
public enum UploadState {INITIALIZED, UPLOADING, CLOSING, UPLOADED} public enum UploadState {INITIALIZED, UPLOADING, CLOSING, UPLOADED}
public UploadState state; public UploadState state;