Fix DataSources
Bug: 118363127
Test: N/A
Change-Id: I56748506f3c93715f9d05ad98a763bd046f59f35
diff --git a/src/main/java/com/android/apksig/internal/util/ChainedDataSource.java b/src/main/java/com/android/apksig/internal/util/ChainedDataSource.java
index 25f23c9..ab56acc 100644
--- a/src/main/java/com/android/apksig/internal/util/ChainedDataSource.java
+++ b/src/main/java/com/android/apksig/internal/util/ChainedDataSource.java
@@ -106,7 +106,7 @@
long beginLocalOffset = firstSource.getSecond();
DataSource beginSource = mSources[beginIndex];
- if (beginLocalOffset + size <= beginSource.size()) {
+ if (beginLocalOffset + size <= beginSource.size() || size == 0) {
return beginSource.slice(beginLocalOffset, size);
}
@@ -115,15 +115,15 @@
sources.add(beginSource.slice(
beginLocalOffset, beginSource.size() - beginLocalOffset));
- Pair<Integer, Long> lastSource = locateDataSource(offset + size);
+ Pair<Integer, Long> lastSource = locateDataSource(offset + size - 1);
int endIndex = lastSource.getFirst();
long endLocalOffset = lastSource.getSecond();
- for (int i = beginIndex + 1; i < endIndex - 1; i++) {
+ for (int i = beginIndex + 1; i < endIndex; i++) {
sources.add(mSources[i]);
}
- sources.add(mSources[endIndex].slice(0, endLocalOffset));
+ sources.add(mSources[endIndex].slice(0, endLocalOffset + 1));
return new ChainedDataSource(sources.toArray(new DataSource[0]));
}
diff --git a/src/main/java/com/android/apksig/internal/util/RandomAccessFileDataSource.java b/src/main/java/com/android/apksig/internal/util/RandomAccessFileDataSource.java
index 3492399..6f59b51 100644
--- a/src/main/java/com/android/apksig/internal/util/RandomAccessFileDataSource.java
+++ b/src/main/java/com/android/apksig/internal/util/RandomAccessFileDataSource.java
@@ -29,19 +29,19 @@
*/
public class RandomAccessFileDataSource implements DataSource {
- private static final int MAX_READ_CHUNK_SIZE = 65536;
+ private static final int MAX_READ_CHUNK_SIZE = 1024 * 1024;
- private final RandomAccessFile mFile;
+ private final FileChannel mChannel;
private final long mOffset;
private final long mSize;
/**
* Constructs a new {@code RandomAccessFileDataSource} based on the data contained in the
- * specified the whole file. Changes to the contents of the file, including the size of the
- * file, will be visible in this data source.
+ * whole file. Changes to the contents of the file, including the size of the file,
+ * will be visible in this data source.
*/
public RandomAccessFileDataSource(RandomAccessFile file) {
- mFile = file;
+ mChannel = file.getChannel();
mOffset = 0;
mSize = -1;
}
@@ -54,13 +54,17 @@
* @throws IndexOutOfBoundsException if {@code offset} or {@code size} is negative.
*/
public RandomAccessFileDataSource(RandomAccessFile file, long offset, long size) {
+ this(file.getChannel(), offset, size);
+ }
+
+ private RandomAccessFileDataSource(FileChannel channel, long offset, long size) {
if (offset < 0) {
throw new IndexOutOfBoundsException("offset: " + size);
}
if (size < 0) {
throw new IndexOutOfBoundsException("size: " + size);
}
- mFile = file;
+ mChannel = channel;
mOffset = offset;
mSize = size;
}
@@ -69,7 +73,7 @@
public long size() {
if (mSize == -1) {
try {
- return mFile.length();
+ return mChannel.size();
} catch (IOException e) {
return 0;
}
@@ -86,7 +90,7 @@
return this;
}
- return new RandomAccessFileDataSource(mFile, mOffset + offset, size);
+ return new RandomAccessFileDataSource(mChannel, mOffset + offset, size);
}
@Override
@@ -99,14 +103,24 @@
long chunkOffsetInFile = mOffset + offset;
long remaining = size;
- byte[] buf = new byte[(int) Math.min(remaining, MAX_READ_CHUNK_SIZE)];
+ ByteBuffer buf = ByteBuffer.allocateDirect((int) Math.min(remaining, MAX_READ_CHUNK_SIZE));
+
while (remaining > 0) {
- int chunkSize = (int) Math.min(remaining, buf.length);
- synchronized (mFile) {
- mFile.seek(chunkOffsetInFile);
- mFile.readFully(buf, 0, chunkSize);
+ int chunkSize = (int) Math.min(remaining, buf.capacity());
+ int chunkRemaining = chunkSize;
+ synchronized (mChannel) {
+ mChannel.position(chunkOffsetInFile);
+ while (chunkRemaining > 0) {
+ int read = mChannel.read(buf);
+ if (read < 0) {
+ throw new IOException("Unexpected EOF encountered");
+ }
+ chunkRemaining -= read;
+ }
}
- sink.consume(buf, 0, chunkSize);
+ buf.flip();
+ sink.consume(buf);
+ buf.clear();
chunkOffsetInFile += chunkSize;
remaining -= chunkSize;
}
@@ -130,12 +144,11 @@
// FileChannel.read(ByteBuffer) reads up to dest.remaining(). Thus, we need to adjust
// the buffer's limit to avoid reading more than size bytes.
dest.limit(dest.position() + size);
- FileChannel fileChannel = mFile.getChannel();
while (remaining > 0) {
int chunkSize;
- synchronized (mFile) {
- fileChannel.position(offsetInFile);
- chunkSize = fileChannel.read(dest);
+ synchronized (mChannel) {
+ mChannel.position(offsetInFile);
+ chunkSize = mChannel.read(dest);
}
offsetInFile += chunkSize;
remaining -= chunkSize;