Make firmware reading a bit more failsafe #30
This commit is contained in:
parent
bdc9e70e6e
commit
910d9ef398
|
@ -8,9 +8,12 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||||
|
|
||||||
public class MiBandFWHelper {
|
public class MiBandFWHelper {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(MiBandFWHelper.class);
|
private static final Logger LOG = LoggerFactory.getLogger(MiBandFWHelper.class);
|
||||||
|
|
||||||
|
@ -29,41 +32,25 @@ public class MiBandFWHelper {
|
||||||
16779568 //1.0.9.48 tested by developer
|
16779568 //1.0.9.48 tested by developer
|
||||||
};
|
};
|
||||||
|
|
||||||
public MiBandFWHelper(Uri uri, Context context) {
|
public MiBandFWHelper(Uri uri, Context context) throws IOException {
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
cr = context.getContentResolver();
|
cr = context.getContentResolver();
|
||||||
|
|
||||||
InputStream fin;
|
try (InputStream in = new BufferedInputStream(cr.openInputStream(uri))){
|
||||||
|
this.fw = FileUtils.readAll(in, 1024 * 1024); // 1 MB
|
||||||
try {
|
if (fw.length > firmwareVersionMajor && fw[firmwareVersionMajor] != 1) {
|
||||||
fin = new BufferedInputStream(cr.openInputStream(uri));
|
throw new IOException("Firmware major version should be 1, probably this isn't a MiBand firmware.");
|
||||||
this.fw = new byte[fin.available()];
|
}
|
||||||
fin.read(fw);
|
|
||||||
fin.close();
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
throw new IOException("Error reading firmware file: " + uri.toString(), e);
|
||||||
this.fw = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fw[firmwareVersionMajor] != 1) {
|
|
||||||
LOG.error("Firmware major version should be 1, probably this isn't a MiBand firmware.");
|
|
||||||
this.fw = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFirmwareVersion() {
|
public int getFirmwareVersion() {
|
||||||
if (fw == null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return (fw[firmwareVersionMajor] << 24) | (fw[firmwareVersionMinor] << 16) | (fw[firmwareVersionRevision] << 8) | fw[firmwareVersionBuild];
|
return (fw[firmwareVersionMajor] << 24) | (fw[firmwareVersionMinor] << 16) | (fw[firmwareVersionRevision] << 8) | fw[firmwareVersionBuild];
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getHumanFirmwareVersion() {
|
public String getHumanFirmwareVersion() {
|
||||||
if (fw == null) {
|
|
||||||
return "UNK";
|
|
||||||
}
|
|
||||||
return String.format(Locale.US, "%d.%d.%d.%d", fw[firmwareVersionMajor], fw[firmwareVersionMinor], fw[firmwareVersionRevision], fw[firmwareVersionBuild]);
|
return String.format(Locale.US, "%d.%d.%d.%d", fw[firmwareVersionMajor], fw[firmwareVersionMinor], fw[firmwareVersionRevision], fw[firmwareVersionBuild]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,5 +81,4 @@ public class MiBandFWHelper {
|
||||||
crc &= 0xffff;
|
crc &= 0xffff;
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -592,6 +592,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInstallApp(Uri uri) {
|
public void onInstallApp(Uri uri) {
|
||||||
|
try {
|
||||||
MiBandFWHelper mFwHelper = new MiBandFWHelper(uri, getContext());
|
MiBandFWHelper mFwHelper = new MiBandFWHelper(uri, getContext());
|
||||||
String mMac = getDevice().getAddress();
|
String mMac = getDevice().getAddress();
|
||||||
String[] mMacOctets = mMac.split(":");
|
String[] mMacOctets = mMac.split(":");
|
||||||
|
@ -605,8 +606,9 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
||||||
newFirmware = mFwHelper.getFw();
|
newFirmware = mFwHelper.getFw();
|
||||||
//the firmware will be sent by the notification listener if the band confirms that the metadata are ok.
|
//the firmware will be sent by the notification listener if the band confirms that the metadata are ok.
|
||||||
}
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
return;
|
GB.toast(getContext(), "Firmware cannot be installed: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package nodomain.freeyourgadget.gadgetbridge.util;
|
package nodomain.freeyourgadget.gadgetbridge.util;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
|
@ -44,4 +46,27 @@ public class FileUtils {
|
||||||
}
|
}
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the contents of the given InputStream into a byte array, but does not
|
||||||
|
* read more than maxLen bytes.
|
||||||
|
* @param in the stream to read from
|
||||||
|
* @param maxLen the maximum number of bytes to read/return
|
||||||
|
* @return the bytes read from the InputStream
|
||||||
|
* @throws IOException when reading failed or when maxLen was exceeded
|
||||||
|
*/
|
||||||
|
public static byte[] readAll(InputStream in, long maxLen) throws IOException {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream(Math.max(8192, in.available()));
|
||||||
|
byte[] buf = new byte[8192];
|
||||||
|
int read = 0;
|
||||||
|
long totalRead = 0;
|
||||||
|
while ((read = in.read(buf)) > 0) {
|
||||||
|
out.write(buf, 0, read);
|
||||||
|
totalRead += read;
|
||||||
|
if (totalRead > maxLen) {
|
||||||
|
throw new IOException("Too much data to read into memory. Got already " + totalRead + buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue