Search in sources :

Example 86 with ZipPath

use of com.android.tools.build.bundletool.model.ZipPath in project bundletool by google.

the class SdkBundleSerializer method writeToDisk.

/**
 * Writes the SDK Bundle on disk at the given location.
 */
public void writeToDisk(SdkBundle bundle, Path pathOnDisk) throws IOException {
    ZipBuilder zipBuilder = new ZipBuilder();
    zipBuilder.addFileWithProtoContent(ZipPath.create(BUNDLE_CONFIG_FILE_NAME), bundle.getBundleConfig());
    // BUNDLE-METADATA
    for (Entry<ZipPath, ByteSource> metadataEntry : bundle.getBundleMetadata().getFileContentMap().entrySet()) {
        zipBuilder.addFile(METADATA_DIRECTORY.resolve(metadataEntry.getKey()), metadataEntry.getValue());
    }
    // Base module (the only module in an ASB)
    BundleModule module = bundle.getModule();
    ZipPath moduleDir = ZipPath.create(module.getName().toString());
    for (ModuleEntry entry : module.getEntries()) {
        ZipPath entryPath = moduleDir.resolve(entry.getPath());
        zipBuilder.addFile(entryPath, entry.getContent());
    }
    // Special module files are not represented as module entries (above).
    zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.ANDROID_MANIFEST.getPath()), module.getAndroidManifest().getManifestRoot().getProto());
    module.getAssetsConfig().ifPresent(assetsConfig -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.ASSETS_TABLE.getPath()), assetsConfig));
    module.getNativeConfig().ifPresent(nativeConfig -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.NATIVE_LIBS_TABLE.getPath()), nativeConfig));
    module.getResourceTable().ifPresent(resourceTable -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.RESOURCE_TABLE.getPath()), resourceTable));
    zipBuilder.writeTo(pathOnDisk);
}
Also used : SpecialModuleEntry(com.android.tools.build.bundletool.model.BundleModule.SpecialModuleEntry) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) ByteSource(com.google.common.io.ByteSource) ZipPath(com.android.tools.build.bundletool.model.ZipPath) BundleModule(com.android.tools.build.bundletool.model.BundleModule)

Example 87 with ZipPath

use of com.android.tools.build.bundletool.model.ZipPath in project bundletool by google.

the class ZipBuilder method writeTo.

/**
 * Writes the data into a zip file.
 *
 * <p>It is an error if the <code>target</code> file already exists.
 *
 * @return The path the .zip file was written to (ie. <code>target</code>).
 * @throws IOException When an I/O error occurs.
 */
public synchronized Path writeTo(Path target) throws IOException {
    // Create temp file and move to requested location when completely written. If the command
    // fails, this prevents us from generating partial output at the user-specified location.
    Path tempFile = Files.createTempFile("ZipBuilder-", ".zip.tmp");
    try {
        try (OutputStream out = BufferedIo.outputStream(tempFile);
            ZipOutputStream outZip = new ZipOutputStream(out)) {
            for (ZipPath path : entries.keySet()) {
                Entry entry = entries.get(path);
                if (entry.getIsDirectory()) {
                    // For directories, we append "/" at the end of the file path since that's what the
                    // ZipEntry class relies on.
                    ZipEntry zipEntry = new ZipEntry(path + "/");
                    zipEntry.setTime(EPOCH);
                    outZip.putNextEntry(zipEntry);
                // Directories are represented as having empty content in a zip file, so we don't write
                // any bytes to the outZip for this entry.
                } else {
                    ZipEntry zipEntry = new ZipEntry(path.toString());
                    zipEntry.setTime(EPOCH);
                    if (entry.hasOption(EntryOption.UNCOMPRESSED)) {
                        zipEntry.setMethod(ZipEntry.STORED);
                        // ZipFile API requires us to set the following properties manually for uncompressed
                        // ZipEntries, just setting the compression method is not enough.
                        ByteSource originalData = entry.getContent().get();
                        // If entry is small enough it would be better to preload it into memory to not
                        // read it twice. Two reads are required because we need to know crc32 before we put
                        // entry content into zip.
                        ByteSource entryData = originalData.size() < PRELOAD_INTO_MEMORY_THRESHOLD ? preloadEntryData(originalData) : originalData;
                        zipEntry.setSize(entryData.size());
                        zipEntry.setCompressedSize(entryData.size());
                        zipEntry.setCrc(entryData.hash(Hashing.crc32()).padToLong());
                        outZip.putNextEntry(zipEntry);
                        entry.getContent().get().copyTo(outZip);
                    } else {
                        outZip.putNextEntry(zipEntry);
                        entry.getContent().get().copyTo(outZip);
                    }
                }
                outZip.closeEntry();
            }
        }
        // Fails if the target file exists.
        Files.move(tempFile, target);
    } finally {
        Files.deleteIfExists(tempFile);
    }
    return target;
}
Also used : ZipPath(com.android.tools.build.bundletool.model.ZipPath) Path(java.nio.file.Path) ZipEntry(java.util.zip.ZipEntry) ZipOutputStream(java.util.zip.ZipOutputStream) OutputStream(java.io.OutputStream) ZipOutputStream(java.util.zip.ZipOutputStream) ZipEntry(java.util.zip.ZipEntry) ByteSource(com.google.common.io.ByteSource) ZipPath(com.android.tools.build.bundletool.model.ZipPath)

Example 88 with ZipPath

use of com.android.tools.build.bundletool.model.ZipPath 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 89 with ZipPath

use of com.android.tools.build.bundletool.model.ZipPath in project bundletool by google.

the class ApkSigner method signEmbeddedApks.

/**
 * Returns a new {@link ModuleSplit} with the same entries as the one given as parameter but with
 * embedded APKs signed.
 */
@CheckReturnValue
public ModuleSplit signEmbeddedApks(ModuleSplit split) {
    ImmutableSet<ZipPath> wear1ApkPaths = ImmutableSet.copyOf(WearApkLocator.findEmbeddedWearApkPaths(split));
    ImmutableList.Builder<ModuleEntry> newEntries = ImmutableList.builder();
    for (ModuleEntry entry : split.getEntries()) {
        ZipPath pathInApk = ApkSerializerHelper.toApkEntryPath(entry.getPath());
        if (entry.getShouldSign() || wear1ApkPaths.contains(pathInApk)) {
            newEntries.add(signModuleEntry(split, entry));
        } else {
            newEntries.add(entry);
        }
    }
    return split.toBuilder().setEntries(newEntries.build()).build();
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) ZipPath(com.android.tools.build.bundletool.model.ZipPath) CheckReturnValue(com.google.errorprone.annotations.CheckReturnValue)

Example 90 with ZipPath

use of com.android.tools.build.bundletool.model.ZipPath in project bundletool by google.

the class AppBundleSerializer method writeToDisk.

/**
 * Writes the App Bundle on disk at the given location.
 */
public void writeToDisk(AppBundle bundle, Path pathOnDisk) throws IOException {
    ZipBuilder zipBuilder = new ZipBuilder();
    EntryOption[] compression = allEntriesUncompressed ? new EntryOption[] { EntryOption.UNCOMPRESSED } : new EntryOption[0];
    zipBuilder.addFileWithProtoContent(ZipPath.create(BUNDLE_CONFIG_FILE_NAME), bundle.getBundleConfig(), compression);
    // APEX bundles do not have metadata files.
    if (bundle.getFeatureModules().isEmpty() || !bundle.isApex()) {
        for (Entry<ZipPath, ByteSource> metadataEntry : bundle.getBundleMetadata().getFileContentMap().entrySet()) {
            zipBuilder.addFile(METADATA_DIRECTORY.resolve(metadataEntry.getKey()), metadataEntry.getValue(), compression);
        }
    }
    for (BundleModule module : bundle.getModules().values()) {
        ZipPath moduleDir = ZipPath.create(module.getName().toString());
        for (ModuleEntry entry : module.getEntries()) {
            ZipPath entryPath = moduleDir.resolve(entry.getPath());
            zipBuilder.addFile(entryPath, entry.getContent(), compression);
        }
        // Special module files are not represented as module entries (above).
        zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.ANDROID_MANIFEST.getPath()), module.getAndroidManifest().getManifestRoot().getProto(), compression);
        module.getAssetsConfig().ifPresent(assetsConfig -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.ASSETS_TABLE.getPath()), assetsConfig, compression));
        module.getNativeConfig().ifPresent(nativeConfig -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.NATIVE_LIBS_TABLE.getPath()), nativeConfig, compression));
        module.getResourceTable().ifPresent(resourceTable -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.RESOURCE_TABLE.getPath()), resourceTable, compression));
        module.getApexConfig().ifPresent(apexConfig -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.APEX_TABLE.getPath()), apexConfig, compression));
        module.getRuntimeEnabledSdkConfig().ifPresent(runtimeEnabledSdkConfig -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.RUNTIME_ENABLED_SDK_CONFIG.getPath()), runtimeEnabledSdkConfig, compression));
    }
    zipBuilder.writeTo(pathOnDisk);
}
Also used : SpecialModuleEntry(com.android.tools.build.bundletool.model.BundleModule.SpecialModuleEntry) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) ByteSource(com.google.common.io.ByteSource) EntryOption(com.android.tools.build.bundletool.io.ZipBuilder.EntryOption) ZipPath(com.android.tools.build.bundletool.model.ZipPath) BundleModule(com.android.tools.build.bundletool.model.BundleModule)

Aggregations

ZipPath (com.android.tools.build.bundletool.model.ZipPath)194 Test (org.junit.Test)154 BuildApksResult (com.android.bundle.Commands.BuildApksResult)106 Path (java.nio.file.Path)55 DeviceSpec (com.android.bundle.Devices.DeviceSpec)44 InvalidBundleException (com.android.tools.build.bundletool.model.exceptions.InvalidBundleException)23 ImmutableSet (com.google.common.collect.ImmutableSet)23 ModuleEntry (com.android.tools.build.bundletool.model.ModuleEntry)19 Variant (com.android.bundle.Commands.Variant)16 ApksArchiveHelpers.createVariant (com.android.tools.build.bundletool.testing.ApksArchiveHelpers.createVariant)15 BundleModule (com.android.tools.build.bundletool.model.BundleModule)13 ImmutableList (com.google.common.collect.ImmutableList)12 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)11 ApksArchiveHelpers.standaloneVariant (com.android.tools.build.bundletool.testing.ApksArchiveHelpers.standaloneVariant)10 Theory (org.junit.experimental.theories.Theory)10 AdbServer (com.android.tools.build.bundletool.device.AdbServer)9 IOException (java.io.IOException)9 ModuleSplit (com.android.tools.build.bundletool.model.ModuleSplit)8 ImmutableSet.toImmutableSet (com.google.common.collect.ImmutableSet.toImmutableSet)8 UncheckedIOException (java.io.UncheckedIOException)8