Search in sources :

Example 1 with BytesSource

use of com.android.zipflinger.BytesSource in project bundletool by google.

the class ZipFlingerApkSerializer method writeProtoApk.

/**
 * Writes an APK for aapt2 to convert to binary.
 *
 * <p>This APK contains only files that aapt2 will convert from proto to binary, and the files
 * needed for the conversion to succeed (e.g. all resources referenced in the resource table).
 *
 * <p>All files are left uncompressed to save aapt2 from re-compressing all the entries it
 * generated since we prefer having control over which compression is used. This is effectively a
 * tradeoff between local storage and CPU.
 *
 * <p>No entry is 4-byte aligned since it's only a temporary APK for aapt2 conversion which won't
 * be actually stored or served to any device.
 */
private void writeProtoApk(ModuleSplit split, Path protoApkPath, TempDirectory tempDir) throws IOException {
    try (ZipArchive apkWriter = new ZipArchive(protoApkPath)) {
        apkWriter.add(new BytesSource(split.getAndroidManifest().getManifestRoot().getProto().toByteArray(), MANIFEST_FILENAME, NO_COMPRESSION.getValue()));
        if (split.getResourceTable().isPresent()) {
            BytesSource bytesSource = new BytesSource(split.getResourceTable().get().toByteArray(), SpecialModuleEntry.RESOURCE_TABLE.getPath().toString(), NO_COMPRESSION.getValue());
            bytesSource.align(4);
            apkWriter.add(bytesSource);
        }
        Map<String, Entry> bundleEntriesByName = bundleZipReader.getEntries();
        ZipEntrySourceFactory sourceFactory = new ZipEntrySourceFactory(bundleZipReader, tempDir);
        for (ModuleEntry moduleEntry : split.getEntries()) {
            ZipPath pathInApk = ApkSerializerHelper.toApkEntryPath(moduleEntry.getPath());
            if (!requiresAapt2Conversion(pathInApk)) {
                continue;
            }
            if (moduleEntry.getBundleLocation().isPresent()) {
                ZipPath pathInBundle = moduleEntry.getBundleLocation().get().entryPathInBundle();
                Entry entry = bundleEntriesByName.get(pathInBundle.toString());
                checkNotNull(entry, "Could not find entry '%s'.", pathInBundle);
                apkWriter.add(sourceFactory.create(entry, pathInApk, NO_COMPRESSION));
            } else {
                apkWriter.add(new BytesSource(moduleEntry.getContent().read(), pathInApk.toString(), NO_COMPRESSION.getValue()));
            }
        }
    }
}
Also used : BytesSource(com.android.zipflinger.BytesSource) SpecialModuleEntry(com.android.tools.build.bundletool.model.BundleModule.SpecialModuleEntry) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) Entry(com.android.zipflinger.Entry) SpecialModuleEntry(com.android.tools.build.bundletool.model.BundleModule.SpecialModuleEntry) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) ZipArchive(com.android.zipflinger.ZipArchive) ZipPath(com.android.tools.build.bundletool.model.ZipPath)

Example 2 with BytesSource

use of com.android.zipflinger.BytesSource in project bundletool by google.

the class ApkSetWriter method zip.

/**
 * Creates ApkSet writer which stores all splits as ZIP archive.
 */
static ApkSetWriter zip(Path tempDirectory, Path outputFile) {
    return new ApkSetWriter() {

        @Override
        public Path getSplitsDirectory() {
            return tempDirectory;
        }

        @Override
        public void writeApkSet(BuildApksResult toc) throws IOException {
            Stream<ApkDescription> apks = toc.getVariantList().stream().flatMap(variant -> variant.getApkSetList().stream()).flatMap(apkSet -> apkSet.getApkDescriptionList().stream());
            Stream<ApkDescription> assets = toc.getAssetSliceSetList().stream().flatMap(assetSliceSet -> assetSliceSet.getApkDescriptionList().stream());
            ImmutableSet<String> apkRelativePaths = Stream.concat(apks, assets).map(ApkDescription::getPath).sorted().collect(toImmutableSet());
            zipApkSet(apkRelativePaths, toc.toByteArray());
        }

        @Override
        public void writeApkSet(BuildSdkApksResult toc) throws IOException {
            Stream<ApkDescription> apks = toc.getVariantList().stream().flatMap(variant -> variant.getApkSetList().stream()).flatMap(apkSet -> apkSet.getApkDescriptionList().stream());
            ImmutableSet<String> apkRelativePaths = apks.map(ApkDescription::getPath).sorted().collect(toImmutableSet());
            zipApkSet(apkRelativePaths, toc.toByteArray());
        }

        private void zipApkSet(ImmutableSet<String> apkRelativePaths, byte[] tocBytes) throws IOException {
            try (ZipArchive zipArchive = new ZipArchive(outputFile)) {
                zipArchive.add(new BytesSource(tocBytes, TABLE_OF_CONTENTS_FILE, Deflater.NO_COMPRESSION));
                for (String relativePath : apkRelativePaths) {
                    zipArchive.add(new LargeFileSource(getSplitsDirectory().resolve(relativePath), /* tmpStorage= */
                    null, relativePath, Deflater.NO_COMPRESSION));
                }
            }
        }
    };
}
Also used : TABLE_OF_CONTENTS_FILE(com.android.tools.build.bundletool.model.utils.FileNames.TABLE_OF_CONTENTS_FILE) ImmutableSet(com.google.common.collect.ImmutableSet) Files(java.nio.file.Files) BuildApksResult(com.android.bundle.Commands.BuildApksResult) BytesSource(com.android.zipflinger.BytesSource) LargeFileSource(com.android.zipflinger.LargeFileSource) IOException(java.io.IOException) Deflater(java.util.zip.Deflater) Stream(java.util.stream.Stream) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) ApkDescription(com.android.bundle.Commands.ApkDescription) ZipArchive(com.android.zipflinger.ZipArchive) BuildSdkApksResult(com.android.bundle.Commands.BuildSdkApksResult) Path(java.nio.file.Path) BuildSdkApksResult(com.android.bundle.Commands.BuildSdkApksResult) BytesSource(com.android.zipflinger.BytesSource) ApkDescription(com.android.bundle.Commands.ApkDescription) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) BuildApksResult(com.android.bundle.Commands.BuildApksResult) ZipArchive(com.android.zipflinger.ZipArchive) LargeFileSource(com.android.zipflinger.LargeFileSource)

Example 3 with BytesSource

use of com.android.zipflinger.BytesSource in project bundletool by google.

the class ZipFlingerAppBundleSerializer method addNewEntries.

/**
 * Adds new and modified entries to an archive, compressing them.
 */
private static void addNewEntries(ZipArchive archive, ImmutableListMultimap<BundleModule, ModuleEntry> entries) throws IOException {
    for (Map.Entry<BundleModule, ModuleEntry> moduleAndEntry : entries.entries()) {
        BundleModule module = moduleAndEntry.getKey();
        ModuleEntry moduleEntry = moduleAndEntry.getValue();
        checkState(!moduleEntry.getBundleLocation().isPresent());
        ZipPath moduleDir = ZipPath.create(module.getName().toString());
        ZipPath destPath = moduleDir.resolve(moduleEntry.getPath());
        archive.add(new BytesSource(moduleEntry.getContent().read(), destPath.toString(), DEFAULT_COMPRESSION_LEVEL));
    }
}
Also used : BytesSource(com.android.zipflinger.BytesSource) SpecialModuleEntry(com.android.tools.build.bundletool.model.BundleModule.SpecialModuleEntry) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) ZipPath(com.android.tools.build.bundletool.model.ZipPath) HashMap(java.util.HashMap) Map(java.util.Map) BundleModule(com.android.tools.build.bundletool.model.BundleModule)

Example 4 with BytesSource

use of com.android.zipflinger.BytesSource in project bundletool by google.

the class ZipFlingerAppBundleSerializer method writeToDisk.

/**
 * Writes the App Bundle on disk at the given location.
 */
public void writeToDisk(AppBundle bundle, Path destBundlePath) throws IOException {
    try (ZipArchive zipArchive = new ZipArchive(destBundlePath)) {
        zipArchive.add(protoToSource(ZipPath.create(BUNDLE_CONFIG_FILE_NAME), bundle.getBundleConfig(), DEFAULT_COMPRESSION_LEVEL));
        // APEX bundles do not have metadata files.
        if (bundle.getFeatureModules().isEmpty() || !bundle.isApex()) {
            for (Map.Entry<ZipPath, ByteSource> metadataEntry : bundle.getBundleMetadata().getFileContentMap().entrySet()) {
                zipArchive.add(new BytesSource(metadataEntry.getValue().read(), METADATA_DIRECTORY.resolve(metadataEntry.getKey()).toString(), DEFAULT_COMPRESSION_LEVEL));
            }
        }
        addEntriesFromSourceBundles(zipArchive, getUnmodifiedModuleEntries(bundle));
        addNewEntries(zipArchive, getNewOrModifiedModuleEntries(bundle));
        // Special module files are not represented as module entries (above).
        for (BundleModule module : bundle.getModules().values()) {
            ZipPath moduleDir = ZipPath.create(module.getName().toString());
            zipArchive.add(protoToSource(moduleDir.resolve(SpecialModuleEntry.ANDROID_MANIFEST.getPath()), module.getAndroidManifest().getManifestRoot().getProto(), DEFAULT_COMPRESSION_LEVEL));
            if (module.getAssetsConfig().isPresent()) {
                zipArchive.add(protoToSource(moduleDir.resolve(SpecialModuleEntry.ASSETS_TABLE.getPath()), module.getAssetsConfig().get(), DEFAULT_COMPRESSION_LEVEL));
            }
            if (module.getNativeConfig().isPresent()) {
                zipArchive.add(protoToSource(moduleDir.resolve(SpecialModuleEntry.NATIVE_LIBS_TABLE.getPath()), module.getNativeConfig().get(), DEFAULT_COMPRESSION_LEVEL));
            }
            if (module.getResourceTable().isPresent()) {
                zipArchive.add(protoToSource(moduleDir.resolve(SpecialModuleEntry.RESOURCE_TABLE.getPath()), module.getResourceTable().get(), DEFAULT_COMPRESSION_LEVEL));
            }
            if (module.getApexConfig().isPresent()) {
                zipArchive.add(protoToSource(moduleDir.resolve(SpecialModuleEntry.APEX_TABLE.getPath()), module.getApexConfig().get(), DEFAULT_COMPRESSION_LEVEL));
            }
        }
    }
}
Also used : BytesSource(com.android.zipflinger.BytesSource) ZipArchive(com.android.zipflinger.ZipArchive) ByteSource(com.google.common.io.ByteSource) ZipPath(com.android.tools.build.bundletool.model.ZipPath) HashMap(java.util.HashMap) Map(java.util.Map) BundleModule(com.android.tools.build.bundletool.model.BundleModule)

Aggregations

BytesSource (com.android.zipflinger.BytesSource)4 ZipPath (com.android.tools.build.bundletool.model.ZipPath)3 ZipArchive (com.android.zipflinger.ZipArchive)3 BundleModule (com.android.tools.build.bundletool.model.BundleModule)2 SpecialModuleEntry (com.android.tools.build.bundletool.model.BundleModule.SpecialModuleEntry)2 ModuleEntry (com.android.tools.build.bundletool.model.ModuleEntry)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 ApkDescription (com.android.bundle.Commands.ApkDescription)1 BuildApksResult (com.android.bundle.Commands.BuildApksResult)1 BuildSdkApksResult (com.android.bundle.Commands.BuildSdkApksResult)1 TABLE_OF_CONTENTS_FILE (com.android.tools.build.bundletool.model.utils.FileNames.TABLE_OF_CONTENTS_FILE)1 Entry (com.android.zipflinger.Entry)1 LargeFileSource (com.android.zipflinger.LargeFileSource)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 ImmutableSet.toImmutableSet (com.google.common.collect.ImmutableSet.toImmutableSet)1 ByteSource (com.google.common.io.ByteSource)1 IOException (java.io.IOException)1 Files (java.nio.file.Files)1 Path (java.nio.file.Path)1