GadgetBridge/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandFWHelper.java

152 lines
5.0 KiB
Java
Raw Normal View History

package nodomain.freeyourgadget.gadgetbridge.devices.miband;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.support.annotation.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.AbstractMiFirmwareInfo;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
/**
* Also see Mi1SFirmwareInfo.
*/
public class MiBandFWHelper {
private static final Logger LOG = LoggerFactory.getLogger(MiBandFWHelper.class);
private final Uri uri;
private final ContentResolver cr;
/**
* The backing firmware info instance, which in general supports the provided
* given firmware. You must call AbstractMiFirmwareInfo#checkValid() before
* attempting to flash it.
*/
private final @NonNull AbstractMiFirmwareInfo firmwareInfo;
private final @NonNull byte[] fw;
/**
* Provides a different notification API which is also used on Mi1A devices.
*/
public static final int FW_16779790 = 16779790;
private final int[] whitelistedFirmwareVersion = {
16779534, // 1.0.9.14 tested by developer
2015-07-28 22:03:53 +02:00
16779547, //1.0.9.27 tested by developer
16779568, //1.0.9.48 tested by developer
16779585, //1.0.9.65 tested by developer
2015-09-17 16:03:15 +02:00
16779779, //1.0.10.3 reported on the wiki
2015-12-07 01:22:27 +01:00
16779782, //1.0.10.6 reported on the wiki
2015-09-17 16:03:15 +02:00
16779787, //1.0.10.11 tested by developer
//FW_16779790, //1.0.10.14 reported on the wiki (vibration does not work currently)
2015-12-07 01:22:27 +01:00
84870926, // 5.15.7.14 tested by developer
};
public MiBandFWHelper(Uri uri, Context context) throws IOException {
this.uri = uri;
cr = context.getContentResolver();
2015-11-23 22:46:12 +01:00
if (cr == null) {
throw new IOException("No content resolver");
}
String pebblePattern = ".*\\.(pbw|pbz|pbl)";
if (uri.getPath().matches(pebblePattern)) {
throw new IOException("Firmware has a filename that looks like a Pebble app/firmware.");
}
try (InputStream in = new BufferedInputStream(cr.openInputStream(uri))) {
this.fw = FileUtils.readAll(in, 1024 * 1024); // 1 MB
this.firmwareInfo = determineFirmwareInfoFor(fw);
} catch (IOException ex) {
throw ex; // pass through
} catch (IllegalArgumentException ex) {
throw new IOException("This doesn't seem to be a Mi Band firmware: " + ex.getLocalizedMessage(), ex);
} catch (Exception e) {
throw new IOException("Error reading firmware file: " + uri.toString(), e);
}
}
public int getFirmwareVersion() {
// FIXME: UnsupportedOperationException!
return firmwareInfo.getFirst().getFirmwareVersion();
}
public int getFirmware2Version() {
return firmwareInfo.getFirst().getFirmwareVersion();
}
public static String formatFirmwareVersion(int version) {
if (version == -1)
return GBApplication.getContext().getString(R.string._unknown_);
return String.format("%d.%d.%d.%d",
version >> 24 & 255,
version >> 16 & 255,
version >> 8 & 255,
version & 255);
}
public String getHumanFirmwareVersion() {
return format(getFirmwareVersion());
}
public String getHumanFirmwareVersion2() {
return format(firmwareInfo.getSecond().getFirmwareVersion());
}
public String format(int version) {
return formatFirmwareVersion(version);
}
public byte[] getFw() {
return fw;
}
public boolean isFirmwareWhitelisted() {
for (int wlf : whitelistedFirmwareVersion) {
if (wlf == getFirmwareVersion()) {
return true;
}
}
return false;
}
public boolean isFirmwareGenerallyCompatibleWith(GBDevice device) {
return firmwareInfo.isGenerallyCompatibleWith(device);
}
public boolean isSingleFirmware() {
return firmwareInfo.isSingleMiBandFirmware();
}
/**
* @param wholeFirmwareBytes
* @return
* @throws IllegalArgumentException when the data is not recognized as firmware data
*/
2016-03-20 15:00:05 +01:00
public static
@NonNull
AbstractMiFirmwareInfo determineFirmwareInfoFor(byte[] wholeFirmwareBytes) {
return AbstractMiFirmwareInfo.determineFirmwareInfoFor(wholeFirmwareBytes);
}
/**
* The backing firmware info instance, which in general supports the provided
* given firmware. You MUST call AbstractMiFirmwareInfo#checkValid() AND
* isGenerallyCompatibleWithDevice() before attempting to flash it.
*/
public AbstractMiFirmwareInfo getFirmwareInfo() {
return firmwareInfo;
}
}