|
|
|
@@ -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.parser.ActivityEntry;
|
|
|
|
|
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.SetDeviceStateRequest;
|
|
|
|
|
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.FileEncryptedGetRequest;
|
|
|
|
|
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.image.AssetImage;
|
|
|
|
|
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.misfit.AnimationRequest;
|
|
|
|
|
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.GB;
|
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
|
|
|
@@ -139,18 +143,16 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|
|
|
|
HashMap<String, Bitmap> appIconCache = new HashMap<>();
|
|
|
|
|
String lastPostedApp = null;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
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;
|
|
|
|
|
enum CONNECTION_MODE {
|
|
|
|
|
NOT_INITIALIZED,
|
|
|
|
|
AUTHENTICATED,
|
|
|
|
|
NOT_AUTHENTICATED
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CONNECTION_MODE connectionMode = CONNECTION_MODE.NOT_INITIALIZED;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void initialize() {
|
|
|
|
|
saveRawActivityFiles = getDeviceSpecificPreferences().getBoolean("save_raw_activity_files", false);
|
|
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
|
|
@@ -162,23 +164,33 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
|
|
negotiateSymmetricKey();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void initializeAfterAuthentication(boolean authenticated){
|
|
|
|
|
queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZING));
|
|
|
|
|
|
|
|
|
|
if(!authenticated) GB.toast("Authentication failed, limited functionality", Toast.LENGTH_LONG, GB.ERROR);
|
|
|
|
|
|
|
|
|
|
loadNotificationConfigurations();
|
|
|
|
|
queueWrite(new NotificationFilterPutHRRequest(this.notificationConfigurations, this));
|
|
|
|
|
|
|
|
|
|
if(authenticated){
|
|
|
|
|
setVibrationStrength();
|
|
|
|
|
|
|
|
|
|
syncSettings();
|
|
|
|
|
|
|
|
|
|
setTime();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
overwriteButtons(null);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
loadBackground();
|
|
|
|
|
loadWidgets();
|
|
|
|
|
// renderWidgets();
|
|
|
|
@@ -187,6 +199,12 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|
|
|
|
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() {
|
|
|
|
|
Prefs prefs = new Prefs(getDeviceSpecificPreferences());
|
|
|
|
|
int vibrationStrengh = prefs.getInt(DeviceSettingsPreferenceConst.PREF_VIBRATION_STRENGH_PERCENTAGE, 2);
|
|
|
|
@@ -198,8 +216,14 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void setVibrationStrength(short strength) {
|
|
|
|
|
negotiateSymmetricKey();
|
|
|
|
|
queueWrite(new ConfigurationPutRequest(new nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest.VibrationStrengthConfigItem((byte) strength), this));
|
|
|
|
|
if(connectionMode == CONNECTION_MODE.NOT_AUTHENTICATED){
|
|
|
|
|
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() {
|
|
|
|
@@ -337,7 +361,6 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void uploadWidgets() {
|
|
|
|
|
negotiateSymmetricKey();
|
|
|
|
|
ArrayList<Widget> systemWidgets = new ArrayList<>(widgets.size());
|
|
|
|
|
for (Widget widget : this.widgets) {
|
|
|
|
|
if (!(widget instanceof CustomWidget) && !widget.getWidgetType().isCustom())
|
|
|
|
@@ -559,8 +582,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|
|
|
|
@Override
|
|
|
|
|
public void downloadFile(final FileHandle handle, boolean fileIsEncrypted) {
|
|
|
|
|
if (fileIsEncrypted) {
|
|
|
|
|
negotiateSymmetricKey();
|
|
|
|
|
queueWrite(new FileEncryptedGetRequest(handle, this) {
|
|
|
|
|
queueWrite((FileEncryptedInterface) new FileEncryptedGetRequest(handle, this) {
|
|
|
|
|
@Override
|
|
|
|
|
public void handleFileData(byte[] fileData) {
|
|
|
|
|
logger.debug("downloaded encrypted file");
|
|
|
|
@@ -589,17 +611,39 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|
|
|
|
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() {
|
|
|
|
|
try {
|
|
|
|
|
queueWrite(new VerifyPrivateKeyRequest(
|
|
|
|
|
this.getSecretKey(),
|
|
|
|
|
this
|
|
|
|
|
));
|
|
|
|
|
){
|
|
|
|
|
@Override
|
|
|
|
|
protected void handleAuthenticationResult(boolean success) {
|
|
|
|
|
FossilHRWatchAdapter.this.handleAuthenticationResult(success);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (IllegalAccessException e) {
|
|
|
|
|
GB.toast("error getting key: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e);
|
|
|
|
|
getDeviceSupport().getDevice().setState(GBDevice.State.AUTHENTICATION_REQUIRED);
|
|
|
|
|
getDeviceSupport().getDevice().sendDeviceUpdateIntent(getContext());
|
|
|
|
|
getDeviceSupport().getQueue().clear();
|
|
|
|
|
this.handleAuthenticationResult(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -614,10 +658,12 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void setTime() {
|
|
|
|
|
negotiateSymmetricKey();
|
|
|
|
|
|
|
|
|
|
if(connectionMode == CONNECTION_MODE.NOT_AUTHENTICATED){
|
|
|
|
|
GB.toast("not available in unauthenticated mode", Toast.LENGTH_LONG, GB.ERROR);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
queueWrite(
|
|
|
|
|
new ConfigurationPutRequest(this.generateTimeConfigItemNow() ,this), false
|
|
|
|
|
(FileEncryptedInterface) new ConfigurationPutRequest(this.generateTimeConfigItemNow(), this)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -659,13 +705,17 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onFetchActivityData() {
|
|
|
|
|
if(connectionMode == CONNECTION_MODE.NOT_AUTHENTICATED){
|
|
|
|
|
GB.toast("not available in unauthenticated mode", Toast.LENGTH_LONG, GB.ERROR);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
syncSettings();
|
|
|
|
|
|
|
|
|
|
negotiateSymmetricKey();
|
|
|
|
|
queueWrite(new FileLookupRequest(FileHandle.ACTIVITY_FILE, this) {
|
|
|
|
|
@Override
|
|
|
|
|
public void handleFileLookup(final short fileHandle) {
|
|
|
|
|
queueWrite(new FileEncryptedGetRequest(fileHandle, FossilHRWatchAdapter.this) {
|
|
|
|
|
queueWrite((FileEncryptedInterface) new FileEncryptedGetRequest(fileHandle, FossilHRWatchAdapter.this) {
|
|
|
|
|
@Override
|
|
|
|
|
public void handleFileData(byte[] fileData) {
|
|
|
|
|
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
|
|
|
@@ -725,9 +775,12 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
@@ -1055,7 +1108,8 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|
|
|
|
if (matcher.find()) {
|
|
|
|
|
firmware = matcher.group(0);
|
|
|
|
|
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[]{
|
|
|
|
|