diff options
author | Paulo Casanova <pasc@google.com> | 2017-08-03 15:25:00 +0100 |
---|---|---|
committer | Paulo Casanova <pasc@google.com> | 2017-08-11 22:13:30 +0000 |
commit | 1ce31f55224a93b1cfca6732ed5b015ecd143514 (patch) | |
tree | d90fff32973eef4e2c55fd467a2673098fe401a9 /src/main/java/com | |
parent | 7d395b86ccfae70cceb793fde97dc8ec11f33b52 (diff) | |
download | apkzlib-1ce31f55224a93b1cfca6732ed5b015ecd143514.tar.gz |
Fix alignment when merging zips.
When merging a zip into an apk, apkzlib used to copy all
the non-ignored files from the zip as-is. This was done to
improve performance as it avoid recompressing files that
were already compressed.
However, if the files need to be uncompressed (for example,
native libraries in M+ devices), this would not ensure that
the libraries were uncompressed: if the libraries were
compressed in the original zip file, they were copied
as-is, i.e., compressed, to the apk breaking alignment.
This CL fixes this by ensuring that files that *need* to
be uncompressed (and only those) are actually added to
the apk following compression and alignment rules.
Test: included
Bug: http://b/37926537
Change-Id: I69848b37ef33b4f0af07dde8c778c7823443d55b
Diffstat (limited to 'src/main/java/com')
-rw-r--r-- | src/main/java/com/android/apkzlib/zfile/ApkZFileCreator.java | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/src/main/java/com/android/apkzlib/zfile/ApkZFileCreator.java b/src/main/java/com/android/apkzlib/zfile/ApkZFileCreator.java index e56f99b..c85ad44 100644 --- a/src/main/java/com/android/apkzlib/zfile/ApkZFileCreator.java +++ b/src/main/java/com/android/apkzlib/zfile/ApkZFileCreator.java @@ -26,6 +26,7 @@ import com.google.common.io.Closer; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.util.function.Function; import java.util.function.Predicate; import javax.annotation.Nonnull; @@ -114,14 +115,30 @@ class ApkZFileCreator implements ApkCreator { try { ZFile toMerge = closer.register(new ZFile(zip)); - Predicate<String> predicate; + Predicate<String> ignorePredicate; if (isIgnored == null) { - predicate = s -> false; + ignorePredicate = s -> false; } else { - predicate = isIgnored; + ignorePredicate = isIgnored; } - this.zip.mergeFrom(toMerge, predicate); + // Files that *must* be uncompressed in the result should not be merged and should be + // added after. This is just very slightly less efficient than ignoring just the ones + // that were compressed and must be uncompressed, but it is a lot simpler :) + Predicate<String> noMergePredicate = ignorePredicate.or(noCompressPredicate); + + this.zip.mergeFrom(toMerge, noMergePredicate); + + for (StoredEntry toMergeEntry : toMerge.entries()) { + String path = toMergeEntry.getCentralDirectoryHeader().getName(); + if (noCompressPredicate.test(path) && !ignorePredicate.test(path)) { + // This entry *must* be uncompressed so it was ignored in the merge and should + // now be added to the apk. + try (InputStream ignoredData = toMergeEntry.open()) { + this.zip.add(path, ignoredData, false); + } + } + } } catch (Throwable t) { throw closer.rethrow(t); } finally { |