Merge "Remove SignApk output limitation of 2GiB" into main am: 605346e5c8
Original change: https://android-review.googlesource.com/c/platform/build/+/3001144 Change-Id: Icd506dcc05860338b034d8ce1a289c3147ce8b92 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -987,6 +987,9 @@ class SignApk {
|
|||||||
|
|
||||||
private static class ZipSections {
|
private static class ZipSections {
|
||||||
DataSource beforeCentralDir;
|
DataSource beforeCentralDir;
|
||||||
|
|
||||||
|
// The following fields are still valid after closing the backing DataSource.
|
||||||
|
long beforeCentralDirSize;
|
||||||
ByteBuffer centralDir;
|
ByteBuffer centralDir;
|
||||||
ByteBuffer eocd;
|
ByteBuffer eocd;
|
||||||
}
|
}
|
||||||
@@ -1006,7 +1009,9 @@ class SignApk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ZipSections result = new ZipSections();
|
ZipSections result = new ZipSections();
|
||||||
|
|
||||||
result.beforeCentralDir = apk.slice(0, centralDirStartOffset);
|
result.beforeCentralDir = apk.slice(0, centralDirStartOffset);
|
||||||
|
result.beforeCentralDirSize = result.beforeCentralDir.size();
|
||||||
|
|
||||||
long centralDirSize = centralDirEndOffset - centralDirStartOffset;
|
long centralDirSize = centralDirEndOffset - centralDirStartOffset;
|
||||||
if (centralDirSize >= Integer.MAX_VALUE) throw new IndexOutOfBoundsException();
|
if (centralDirSize >= Integer.MAX_VALUE) throw new IndexOutOfBoundsException();
|
||||||
@@ -1270,11 +1275,8 @@ class SignApk {
|
|||||||
// signatures)
|
// signatures)
|
||||||
apkSigner.inputApkSigningBlock(null);
|
apkSigner.inputApkSigningBlock(null);
|
||||||
|
|
||||||
// Build the output APK in memory, by copying input APK's ZIP entries across
|
|
||||||
// and then signing the output APK.
|
|
||||||
ByteArrayOutputStream v1SignedApkBuf = new ByteArrayOutputStream();
|
|
||||||
CountingOutputStream outputJarCounter =
|
CountingOutputStream outputJarCounter =
|
||||||
new CountingOutputStream(v1SignedApkBuf);
|
new CountingOutputStream(outputFile);
|
||||||
JarOutputStream outputJar = new JarOutputStream(outputJarCounter);
|
JarOutputStream outputJar = new JarOutputStream(outputJarCounter);
|
||||||
// Use maximum compression for compressed entries because the APK lives forever
|
// Use maximum compression for compressed entries because the APK lives forever
|
||||||
// on the system partition.
|
// on the system partition.
|
||||||
@@ -1287,10 +1289,13 @@ class SignApk {
|
|||||||
addV1Signature(apkSigner, addV1SignatureRequest, outputJar, timestamp);
|
addV1Signature(apkSigner, addV1SignatureRequest, outputJar, timestamp);
|
||||||
addV1SignatureRequest.done();
|
addV1SignatureRequest.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// close output and switch to input mode
|
||||||
outputJar.close();
|
outputJar.close();
|
||||||
ByteBuffer v1SignedApk = ByteBuffer.wrap(v1SignedApkBuf.toByteArray());
|
outputJar = null;
|
||||||
v1SignedApkBuf.reset();
|
outputJarCounter = null;
|
||||||
ByteBuffer[] outputChunks = new ByteBuffer[] {v1SignedApk};
|
outputFile = null;
|
||||||
|
RandomAccessFile v1SignedApk = new RandomAccessFile(outputFilename, "r");
|
||||||
|
|
||||||
ZipSections zipSections = findMainZipSections(DataSources.asDataSource(
|
ZipSections zipSections = findMainZipSections(DataSources.asDataSource(
|
||||||
v1SignedApk));
|
v1SignedApk));
|
||||||
@@ -1299,6 +1304,9 @@ class SignApk {
|
|||||||
eocd.put(zipSections.eocd);
|
eocd.put(zipSections.eocd);
|
||||||
eocd.flip();
|
eocd.flip();
|
||||||
eocd.order(ByteOrder.LITTLE_ENDIAN);
|
eocd.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
|
ByteBuffer[] outputChunks = new ByteBuffer[] {};
|
||||||
|
|
||||||
// This loop is supposed to be iterated twice at most.
|
// This loop is supposed to be iterated twice at most.
|
||||||
// The second pass is to align the file size after amending EOCD comments
|
// The second pass is to align the file size after amending EOCD comments
|
||||||
// with assumption that re-generated signing block would be the same size.
|
// with assumption that re-generated signing block would be the same size.
|
||||||
@@ -1325,13 +1333,8 @@ class SignApk {
|
|||||||
modifiedEocd,
|
modifiedEocd,
|
||||||
zipSections.beforeCentralDir.size() + padding +
|
zipSections.beforeCentralDir.size() + padding +
|
||||||
apkSigningBlock.length);
|
apkSigningBlock.length);
|
||||||
if (zipSections.beforeCentralDir.size() >= Integer.MAX_VALUE) {
|
|
||||||
throw new IndexOutOfBoundsException();
|
|
||||||
}
|
|
||||||
outputChunks =
|
outputChunks =
|
||||||
new ByteBuffer[] {
|
new ByteBuffer[] {
|
||||||
zipSections.beforeCentralDir.getByteBuffer(0,
|
|
||||||
(int)zipSections.beforeCentralDir.size()),
|
|
||||||
ByteBuffer.allocate(padding),
|
ByteBuffer.allocate(padding),
|
||||||
ByteBuffer.wrap(apkSigningBlock),
|
ByteBuffer.wrap(apkSigningBlock),
|
||||||
zipSections.centralDir,
|
zipSections.centralDir,
|
||||||
@@ -1345,7 +1348,7 @@ class SignApk {
|
|||||||
|
|
||||||
// Calculate the file size
|
// Calculate the file size
|
||||||
eocd = modifiedEocd;
|
eocd = modifiedEocd;
|
||||||
int fileSize = 0;
|
long fileSize = zipSections.beforeCentralDirSize;
|
||||||
for (ByteBuffer buf : outputChunks) {
|
for (ByteBuffer buf : outputChunks) {
|
||||||
fileSize += buf.remaining();
|
fileSize += buf.remaining();
|
||||||
}
|
}
|
||||||
@@ -1354,7 +1357,7 @@ class SignApk {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Pad EOCD comment to align the file size.
|
// Pad EOCD comment to align the file size.
|
||||||
int commentLen = alignment - fileSize % alignment;
|
int commentLen = alignment - (int)(fileSize % alignment);
|
||||||
modifiedEocd = ByteBuffer.allocate(eocd.remaining() + commentLen);
|
modifiedEocd = ByteBuffer.allocate(eocd.remaining() + commentLen);
|
||||||
modifiedEocd.put(eocd);
|
modifiedEocd.put(eocd);
|
||||||
modifiedEocd.rewind();
|
modifiedEocd.rewind();
|
||||||
@@ -1365,6 +1368,12 @@ class SignApk {
|
|||||||
eocd = modifiedEocd;
|
eocd = modifiedEocd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// close input and switch back to output mode
|
||||||
|
v1SignedApk.close();
|
||||||
|
v1SignedApk = null;
|
||||||
|
outputFile = new FileOutputStream(outputFilename, true);
|
||||||
|
outputFile.getChannel().truncate(zipSections.beforeCentralDirSize);
|
||||||
|
|
||||||
// This assumes outputChunks are array-backed. To avoid this assumption, the
|
// This assumes outputChunks are array-backed. To avoid this assumption, the
|
||||||
// code could be rewritten to use FileChannel.
|
// code could be rewritten to use FileChannel.
|
||||||
for (ByteBuffer outputChunk : outputChunks) {
|
for (ByteBuffer outputChunk : outputChunks) {
|
||||||
|
Reference in New Issue
Block a user