Annotations added, warnings removed

This commit is contained in:
Aleksander Nowakowski 2018-12-04 10:54:49 +01:00
parent a37e5328d7
commit ac585ac926
1 changed files with 136 additions and 120 deletions

View File

@ -22,6 +22,8 @@
package no.nordicsemi.android.dfu.internal; package no.nordicsemi.android.dfu.internal;
import android.support.annotation.NonNull;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.FilterInputStream; import java.io.FilterInputStream;
@ -31,13 +33,15 @@ import java.io.InputStream;
import no.nordicsemi.android.dfu.internal.exception.HexFileValidationException; import no.nordicsemi.android.dfu.internal.exception.HexFileValidationException;
/** /**
* Reads the binary content from the HEX file using IntelHex standard: http://www.interlog.com/~speff/usefulinfo/Hexfrmt.pdf. * Reads the binary content from the HEX file using IntelHex standard:
* http://www.interlog.com/~speff/usefulinfo/Hexfrmt.pdf.
* Truncates the HEX file from all meta data and returns only the BIN content. * Truncates the HEX file from all meta data and returns only the BIN content.
* <p> * <p>
* In nRF51 chips memory a SoftDevice starts at address 0x1000. From 0x0000 to 0x1000 there is MBR sector (since SoftDevice 7.0.0) which should not be transmitted using DFU. Therefore this class skips * In nRF51 chips memory a SoftDevice starts at address 0x1000. From 0x0000 to 0x1000 there is
* all data from addresses below 0x1000. * MBR sector (since SoftDevice 7.0.0) which should not be transmitted using DFU. Therefore this
* </p> * class skips all data from addresses below 0x1000.
*/ */
@SuppressWarnings({"WeakerAccess", "unused"})
public class HexInputStream extends FilterInputStream { public class HexInputStream extends FilterInputStream {
private final int LINE_LENGTH = 128; private final int LINE_LENGTH = 128;
@ -50,18 +54,18 @@ public class HexInputStream extends FilterInputStream {
private final int MBRSize; private final int MBRSize;
/** /**
* Creates the HEX Input Stream. The constructor calculates the size of the BIN content which is available through {@link #sizeInBytes()}. If HEX file is invalid then the bin size is 0. * Creates the HEX Input Stream. The constructor calculates the size of the BIN content which
* is available through {@link #sizeInBytes()}. If HEX file is invalid then the bin size is 0.
* *
* @param in * @param in the input stream to read from.
* the input stream to read from * @param mbrSize the MBR (Master Boot Record) size in bytes. Data with addresses below than
* @param mbrSize * number will be trimmed and not transferred to DFU target.
* The MBR (Master Boot Record) size in bytes. Data with addresses below than number will be trimmed and not transferred to DFU target. * @throws HexFileValidationException if HEX file is invalid, e.g. there is no semicolon (':')
* @throws HexFileValidationException * on the beginning of each line.
* if HEX file is invalid. F.e. there is no semicolon (':') on the beginning of each line. * @throws IOException if the stream is closed or another IOException occurs.
* @throws java.io.IOException
* if the stream is closed or another IOException occurs.
*/ */
public HexInputStream(final InputStream in, final int mbrSize) throws HexFileValidationException, IOException { public HexInputStream(@NonNull final InputStream in, final int mbrSize)
throws HexFileValidationException, IOException {
super(new BufferedInputStream(in)); super(new BufferedInputStream(in));
this.localBuf = new byte[LINE_LENGTH]; this.localBuf = new byte[LINE_LENGTH];
this.localPos = LINE_LENGTH; // we are at the end of the local buffer, new one must be obtained this.localPos = LINE_LENGTH; // we are at the end of the local buffer, new one must be obtained
@ -72,7 +76,19 @@ public class HexInputStream extends FilterInputStream {
this.available = calculateBinSize(mbrSize); this.available = calculateBinSize(mbrSize);
} }
public HexInputStream(final byte[] data, final int mbrSize) throws HexFileValidationException, IOException { /**
* Creates the HEX Input Stream. The constructor calculates the size of the BIN content which
* is available through {@link #sizeInBytes()}. If HEX file is invalid then the bin size is 0.
*
* @param data the input stream to read from.
* @param mbrSize the MBR (Master Boot Record) size in bytes. Data with addresses below than
* * number will be trimmed and not transferred to DFU target.
* @throws HexFileValidationException if HEX file is invalid, e.g. there is no semicolon (':')
* on the beginning of each line.
* @throws IOException if the stream is closed or another IOException occurs.
*/
public HexInputStream(@NonNull final byte[] data, final int mbrSize)
throws HexFileValidationException, IOException {
super(new ByteArrayInputStream(data)); super(new ByteArrayInputStream(data));
this.localBuf = new byte[LINE_LENGTH]; this.localBuf = new byte[LINE_LENGTH];
this.localPos = LINE_LENGTH; // we are at the end of the local buffer, new one must be obtained this.localPos = LINE_LENGTH; // we are at the end of the local buffer, new one must be obtained
@ -83,6 +99,7 @@ public class HexInputStream extends FilterInputStream {
this.available = calculateBinSize(mbrSize); this.available = calculateBinSize(mbrSize);
} }
@SuppressWarnings("ResultOfMethodCallIgnored")
private int calculateBinSize(final int mbrSize) throws IOException { private int calculateBinSize(final int mbrSize) throws IOException {
int binSize = 0; int binSize = 0;
final InputStream in = this.in; final InputStream in = this.in;
@ -106,8 +123,11 @@ public class HexInputStream extends FilterInputStream {
case 0x04: { case 0x04: {
// extended linear address record // extended linear address record
/* /*
* The HEX file may contain jump to different addresses. The MSB of LBA (Linear Base Address) is given using the line type 4. * The HEX file may contain jump to different addresses.
* We only support files where bytes are located together, no jumps are allowed. Therefore the newULBA may be only lastULBA + 1 (or any, if this is the first line of the HEX) * The MSB of LBA (Linear Base Address) is given using the line type 4.
* We only support files where bytes are located together, no jumps are
* allowed. Therefore the newULBA may be only lastULBA + 1 (or any,
* if this is the first line of the HEX)
*/ */
final int newULBA = readAddress(in); final int newULBA = readAddress(in);
if (binSize > 0 && newULBA != (lastBaseAddress >> 16) + 1) if (binSize > 0 && newULBA != (lastBaseAddress >> 16) + 1)
@ -128,7 +148,10 @@ public class HexInputStream extends FilterInputStream {
case 0x00: case 0x00:
// data type line // data type line
lastAddress = lastBaseAddress + offset; lastAddress = lastBaseAddress + offset;
if (lastAddress >= mbrSize) // we must skip all data from below last MBR address (default 0x1000) as those are the MBR. The Soft Device starts at the end of MBR (0x1000), the app and bootloader farther more // we must skip all data from below last MBR address (default 0x1000)
// as those are the MBR. The Soft Device starts at the end of MBR (0x1000),
// the app and bootloader farther more
if (lastAddress >= mbrSize)
binSize += lineSize; binSize += lineSize;
// no break! // no break!
default: default:
@ -137,13 +160,9 @@ public class HexInputStream extends FilterInputStream {
break; break;
} }
// skip end of line // skip end of line
while (true) { do {
b = in.read(); b = in.read();
} while (b == '\n' || b == '\r');
if (b != '\n' && b != '\r') {
break;
}
}
} }
} finally { } finally {
in.reset(); in.reset();
@ -160,9 +179,8 @@ public class HexInputStream extends FilterInputStream {
* *
* @param buffer buffer to be filled * @param buffer buffer to be filled
* @return the size of the buffer * @return the size of the buffer
* @throws java.io.IOException
*/ */
public int readPacket(byte[] buffer) throws HexFileValidationException, IOException { public int readPacket(@NonNull byte[] buffer) throws IOException {
int i = 0; int i = 0;
while (i < buffer.length) { while (i < buffer.length) {
if (localPos < size) { if (localPos < size) {
@ -178,17 +196,17 @@ public class HexInputStream extends FilterInputStream {
} }
@Override @Override
public int read() throws IOException { public int read() {
throw new UnsupportedOperationException("Please, use readPacket() method instead"); throw new UnsupportedOperationException("Please, use readPacket() method instead");
} }
@Override @Override
public int read(byte[] buffer) throws IOException { public int read(@NonNull byte[] buffer) throws IOException {
return readPacket(buffer); return readPacket(buffer);
} }
@Override @Override
public int read(byte[] buffer, int offset, int count) throws IOException { public int read(@NonNull byte[] buffer, int offset, int count) {
throw new UnsupportedOperationException("Please, use readPacket() method instead"); throw new UnsupportedOperationException("Please, use readPacket() method instead");
} }
@ -202,25 +220,24 @@ public class HexInputStream extends FilterInputStream {
} }
/** /**
* Returns the total number of packets with given size that are needed to get all available data * Returns the total number of packets with given size that are needed to get all
* available data.
* *
* @param packetSize * @param packetSize the maximum packet size
* the maximum packet size
* @return the number of packets needed to get all the content * @return the number of packets needed to get all the content
* @throws java.io.IOException
*/ */
public int sizeInPackets(final int packetSize) throws IOException { public int sizeInPackets(final int packetSize) {
final int sizeInBytes = sizeInBytes(); final int sizeInBytes = sizeInBytes();
return sizeInBytes / packetSize + ((sizeInBytes % packetSize) > 0 ? 1 : 0); return sizeInBytes / packetSize + ((sizeInBytes % packetSize) > 0 ? 1 : 0);
} }
/** /**
* Reads new line from the input stream. Input stream must be a HEX file. The first line is always skipped. * Reads new line from the input stream. Input stream must be a HEX file.
* The first line is always skipped.
* *
* @return the number of data bytes in the new line. 0 if end of file. * @return the number of data bytes in the new line. 0 if end of file.
* @throws java.io.IOException * @throws java.io.IOException if this stream is closed or another IOException occurs.
* if this stream is closed or another IOException occurs.
*/ */
private int readLine() throws IOException { private int readLine() throws IOException {
// end of file reached // end of file reached
@ -234,23 +251,21 @@ public class HexInputStream extends FilterInputStream {
int lineSize, type, offset; int lineSize, type, offset;
do { do {
// skip end of line // skip end of line
while (true) { do {
b = in.read(); b = in.read();
pos++; pos++;
} while (b == '\n' || b == '\r');
if (b != '\n' && b != '\r') {
break;
}
}
/* /*
* Each line starts with comma (':') * Each line starts with comma (':')
* Data is written in HEX, so each 2 ASCII letters give one byte. * Data is written in HEX, so each 2 ASCII letters give one byte.
* After the comma there is one byte (2 HEX signs) with line length (normally 10 -> 0x10 -> 16 bytes -> 32 HEX characters) * After the comma there is one byte (2 HEX signs) with line length
* (normally 10 -> 0x10 -> 16 bytes -> 32 HEX characters)
* After that there is a 4 byte of an address. This part may be skipped. * After that there is a 4 byte of an address. This part may be skipped.
* There is a packet type after the address (1 byte = 2 HEX characters). 00 is the valid data. Other values can be skipped when * There is a packet type after the address (1 byte = 2 HEX characters).
* converting to BIN file. * 00 is the valid data. Other values can be skipped when converting to BIN file.
* Then goes n bytes of data followed by 1 byte (2 HEX chars) of checksum, which is also skipped in BIN file. * Then goes n bytes of data followed by 1 byte (2 HEX chars) of checksum,
* which is also skipped in BIN file.
*/ */
checkComma(b); // checking the comma at the beginning checkComma(b); // checking the comma at the beginning
lineSize = readByte(in); // reading the length of the data in this line lineSize = readByte(in); // reading the length of the data in this line
@ -326,22 +341,23 @@ public class HexInputStream extends FilterInputStream {
throw new HexFileValidationException("Not a HEX file"); throw new HexFileValidationException("Not a HEX file");
} }
private long skip(final InputStream in, final long offset) throws IOException { private long skip(@NonNull final InputStream in, final long offset) throws IOException {
long skipped = in.skip(offset); long skipped = in.skip(offset);
// try to skip 2 times as skip(..) method does not guarantee to skip exactly given number of bytes // try to skip 2 times as skip(..) method does not guarantee to skip exactly
// given number of bytes
if (skipped < offset) if (skipped < offset)
skipped += in.skip(offset - skipped); skipped += in.skip(offset - skipped);
return skipped; return skipped;
} }
private int readByte(final InputStream in) throws IOException { private int readByte(@NonNull final InputStream in) throws IOException {
final int first = asciiToInt(in.read()); final int first = asciiToInt(in.read());
final int second = asciiToInt(in.read()); final int second = asciiToInt(in.read());
return first << 4 | second; return first << 4 | second;
} }
private int readAddress(final InputStream in) throws IOException { private int readAddress(@NonNull final InputStream in) throws IOException {
return readByte(in) << 8 | readByte(in); return readByte(in) << 8 | readByte(in);
} }