Search in sources :

Example 6 with BundleConfig

use of com.android.bundle.Config.BundleConfig in project bundletool by google.

the class BuildBundleCommandTest method bundleConfig_saved.

@Test
public void bundleConfig_saved() throws Exception {
    Path module = createSimpleBaseModule();
    // Any version supplied by the user is ignored and overwritten.
    BundleConfig bundleConfigFromUser = BundleConfigBuilder.create().setVersion("0.0.0").build();
    BundleConfig bundleConfigInBundle = new BundleConfigBuilder(bundleConfigFromUser).setVersion(BundleToolVersion.getCurrentVersion().toString()).build();
    assertThat(bundleConfigFromUser.getBundletool().getVersion()).isNotEqualTo(bundleConfigInBundle.getBundletool().getVersion());
    BuildBundleCommand.builder().setModulesPaths(ImmutableList.of(module)).setOutputPath(bundlePath).setBundleConfig(bundleConfigFromUser).build().execute();
    try (ZipFile appBundleZip = new ZipFile(bundlePath.toFile())) {
        AppBundle appBundle = AppBundle.buildFromZip(appBundleZip);
        assertThat(appBundle.getBundleConfig()).isEqualTo(bundleConfigInBundle);
    }
}
Also used : Path(java.nio.file.Path) ZipPath(com.android.tools.build.bundletool.model.ZipPath) BundleConfig(com.android.bundle.Config.BundleConfig) AppBundle(com.android.tools.build.bundletool.model.AppBundle) BundleConfigBuilder(com.android.tools.build.bundletool.testing.BundleConfigBuilder) ZipFile(java.util.zip.ZipFile) Test(org.junit.Test)

Example 7 with BundleConfig

use of com.android.bundle.Config.BundleConfig in project bundletool by google.

the class AppBundleRecompressor method extractBundleConfig.

private static BundleConfig extractBundleConfig(ZipReader zipReader) {
    // The bundle hasn't been validated yet, therefore selected validations need to be run manually.
    if (!zipReader.getEntry(AppBundle.BUNDLE_CONFIG_FILE_NAME).isPresent()) {
        throw InvalidBundleException.builder().withUserMessage("The archive doesn't seem to be an App Bundle, it is missing required file '%s'.", AppBundle.BUNDLE_CONFIG_FILE_NAME).build();
    }
    try (InputStream inputStream = zipReader.getUncompressedPayload(AppBundle.BUNDLE_CONFIG_FILE_NAME)) {
        BundleConfig bundleConfig = BundleConfig.parseFrom(inputStream, ExtensionRegistryLite.getEmptyRegistry());
        new BundleConfigValidator().validateCompression(bundleConfig.getCompression());
        return bundleConfig;
    } catch (IOException e) {
        throw new UncheckedIOException(e);
    }
}
Also used : BundleConfig(com.android.bundle.Config.BundleConfig) InputStream(java.io.InputStream) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) BundleConfigValidator(com.android.tools.build.bundletool.validation.BundleConfigValidator)

Example 8 with BundleConfig

use of com.android.bundle.Config.BundleConfig in project bundletool by google.

the class ModuleSplitSerializer method serialize.

/**
 * Serializes module splits on disk under {@code outputDirectory}.
 *
 * <p>Returns {@link ApkDescription} for each serialized split keyed by relative path of module
 * split.
 */
public ImmutableMap<ZipPath, ApkDescription> serialize(Path outputDirectory, ImmutableMap<ZipPath, ModuleSplit> splitsByRelativePath) {
    // Prepare original splits by:
    // * signing embedded APKs
    // * injecting manifest and resource table as module entries.
    ImmutableList<ModuleSplit> preparedSplits = splitsByRelativePath.values().stream().map(apkSigner::signEmbeddedApks).map(ModuleSplitSerializer::injectManifestAndResourceTableAsEntries).collect(toImmutableList());
    try (SerializationFilesManager filesManager = new SerializationFilesManager()) {
        // Convert module splits to binary format and apply uncompressed globs specified in
        // BundleConfig. We do it in this order because as specified in documentation the matching
        // for uncompressed globs is done against paths in final APKs.
        ImmutableList<ModuleSplit> binarySplits = aapt2ResourceConverter.convert(preparedSplits, filesManager).stream().map(this::applyUncompressedGlobsAndUncompressedNativeLibraries).collect(toImmutableList());
        // Build a pack from entries which may be compressed inside final APKs. 'May be
        // compressed' means that for these entries we will decide later should they be compressed
        // or not based on whether we gain enough savings from compression.
        ModuleEntriesPack maybeCompressedEntriesPack = buildCompressedEntriesPack(filesManager.getCompressedResourceEntriesPackPath(), filesManager.getCompressedEntriesPackPath(), binarySplits);
        // Build a pack with entries that are uncompressed in final APKs: force uncompressed entries
        // + entries that have very low compression ratio.
        ModuleEntriesPack uncompressedEntriesPack = buildUncompressedEntriesPack(filesManager.getUncompressedEntriesPackPath(), binarySplits, maybeCompressedEntriesPack);
        // Now content of all binary apks is already moved to compressed/uncompressed packs. Delete
        // them to free space.
        filesManager.closeAndRemoveBinaryApks();
        // Merge two packs together, so we have all entries for final APKs inside one pack. If the
        // same entry is in both packs we prefer uncompressed one, because it means this entry
        // has very low compression ratio, it makes no sense to put it in compressed form.
        ModuleEntriesPack allEntriesPack = maybeCompressedEntriesPack.mergeWith(uncompressedEntriesPack);
        // Serialize and sign final APKs.
        ImmutableList<ListenableFuture<ApkDescription>> apkDescriptions = Streams.zip(splitsByRelativePath.keySet().stream(), binarySplits.stream(), (relativePath, split) -> executorService.submit(() -> serializeAndSignSplit(outputDirectory, relativePath, split, allEntriesPack, uncompressedEntriesPack))).collect(toImmutableList());
        return ConcurrencyUtils.waitForAll(apkDescriptions).stream().collect(toImmutableMap(apk -> ZipPath.create(apk.getPath()), identity()));
    } catch (IOException e) {
        throw new UncheckedIOException(e);
    }
}
Also used : PathMatcher(com.android.tools.build.bundletool.model.utils.PathMatcher) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) ZipPath(com.android.tools.build.bundletool.model.ZipPath) ApkListener(com.android.tools.build.bundletool.model.ApkListener) Inject(javax.inject.Inject) ApkSerializerHelper.toApkEntryPath(com.android.tools.build.bundletool.io.ApkSerializerHelper.toApkEntryPath) ImmutableList(com.google.common.collect.ImmutableList) ApkDescription(com.android.bundle.Commands.ApkDescription) ZipArchive(com.android.zipflinger.ZipArchive) Version(com.android.tools.build.bundletool.model.version.Version) ByteSource(com.google.common.io.ByteSource) Path(java.nio.file.Path) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Collection(java.util.Collection) ApkSerializerHelper.requiresAapt2Conversion(com.android.tools.build.bundletool.io.ApkSerializerHelper.requiresAapt2Conversion) IOException(java.io.IOException) Deflater(java.util.zip.Deflater) VerboseLogs(com.android.tools.build.bundletool.commands.BuildApksModule.VerboseLogs) Streams(com.google.common.collect.Streams) Entry(com.android.zipflinger.Entry) ZipSource(com.android.zipflinger.ZipSource) SpecialModuleEntry(com.android.tools.build.bundletool.model.BundleModule.SpecialModuleEntry) UncheckedIOException(java.io.UncheckedIOException) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) ModuleSplit(com.android.tools.build.bundletool.model.ModuleSplit) BundleConfig(com.android.bundle.Config.BundleConfig) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) NO_DEFAULT_UNCOMPRESS_EXTENSIONS(com.android.tools.build.bundletool.model.version.VersionGuardedFeature.NO_DEFAULT_UNCOMPRESS_EXTENSIONS) Function.identity(java.util.function.Function.identity) Optional(java.util.Optional) Pattern(java.util.regex.Pattern) Comparator(java.util.Comparator) FileUtils(com.android.tools.build.bundletool.model.utils.files.FileUtils) ListeningExecutorService(com.google.common.util.concurrent.ListeningExecutorService) ModuleSplit(com.android.tools.build.bundletool.model.ModuleSplit) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException)

Example 9 with BundleConfig

use of com.android.bundle.Config.BundleConfig in project bundletool by google.

the class TextureCompressionFormatParityValidator method validateBundle.

@Override
public void validateBundle(AppBundle bundle) {
    BundleConfig bundleConfig = bundle.getBundleConfig();
    Optimizations optimizations = bundleConfig.getOptimizations();
    List<SplitDimension> splitDimensions = optimizations.getSplitsConfig().getSplitDimensionList();
    Optional<String> tcfDefaultSuffix = splitDimensions.stream().filter(dimension -> dimension.getValue().equals(Value.TEXTURE_COMPRESSION_FORMAT)).map(dimension -> dimension.getSuffixStripping().getDefaultSuffix()).collect(toOptional());
    if (tcfDefaultSuffix.isPresent()) {
        // Get the default texture compression format targeting, or an empty optional if fallback
        // must be used.
        Optional<TextureCompressionFormatTargeting> defaultTextureCompressionFormat = Optional.ofNullable(TextureCompressionUtils.TEXTURE_TO_TARGETING.get(tcfDefaultSuffix.get()));
        validateFormatSupportedByAllModules(bundle, defaultTextureCompressionFormat);
    }
}
Also used : MoreCollectors.toOptional(com.google.common.collect.MoreCollectors.toOptional) ImmutableSet(com.google.common.collect.ImmutableSet) Value(com.android.bundle.Config.SplitDimension.Value) Optimizations(com.android.bundle.Config.Optimizations) InvalidBundleException(com.android.tools.build.bundletool.model.exceptions.InvalidBundleException) TargetedDirectory(com.android.tools.build.bundletool.model.targeting.TargetedDirectory) TargetingDimension(com.android.tools.build.bundletool.model.targeting.TargetingDimension) List(java.util.List) TextureCompressionUtils(com.android.tools.build.bundletool.model.utils.TextureCompressionUtils) ImmutableList(com.google.common.collect.ImmutableList) BundleConfig(com.android.bundle.Config.BundleConfig) SplitDimension(com.android.bundle.Config.SplitDimension) AssetsDirectoryTargeting(com.android.bundle.Targeting.AssetsDirectoryTargeting) TextureCompressionFormatTargeting(com.android.bundle.Targeting.TextureCompressionFormatTargeting) AutoValue(com.google.auto.value.AutoValue) Optional(java.util.Optional) TargetingUtils.extractTextureCompressionFormats(com.android.tools.build.bundletool.model.targeting.TargetingUtils.extractTextureCompressionFormats) TextureCompressionFormatAlias(com.android.bundle.Targeting.TextureCompressionFormat.TextureCompressionFormatAlias) TargetingUtils.extractAssetsTargetedDirectories(com.android.tools.build.bundletool.model.targeting.TargetingUtils.extractAssetsTargetedDirectories) AppBundle(com.android.tools.build.bundletool.model.AppBundle) BundleModule(com.android.tools.build.bundletool.model.BundleModule) BundleConfig(com.android.bundle.Config.BundleConfig) SplitDimension(com.android.bundle.Config.SplitDimension) TextureCompressionFormatTargeting(com.android.bundle.Targeting.TextureCompressionFormatTargeting) Optimizations(com.android.bundle.Config.Optimizations)

Example 10 with BundleConfig

use of com.android.bundle.Config.BundleConfig in project bundletool by google.

the class AppBundleRecompressor method recompressAppBundle.

public void recompressAppBundle(File inputFile, File outputFile) {
    try (ZipReader zipReader = ZipReader.createFromFile(inputFile.toPath());
        ZipArchive newBundle = new ZipArchive(outputFile);
        TempDirectory tempDirectory = new TempDirectory(getClass().getSimpleName())) {
        ZipEntrySourceFactory sourceFactory = new ZipEntrySourceFactory(zipReader, tempDirectory);
        List<ListenableFuture<ZipEntrySource>> sources = new ArrayList<>();
        BundleConfig bundleConfig = extractBundleConfig(zipReader);
        ImmutableSet<String> uncompressedAssetsModules = extractModulesWithUncompressedAssets(zipReader, bundleConfig);
        CompressionManager compressionManager = new CompressionManager(bundleConfig, uncompressedAssetsModules);
        for (Entry entry : zipReader.getEntries().values()) {
            CompressionLevel compressionLevel = compressionManager.getCompressionLevel(entry);
            // parallelization there either.
            if (compressionLevel.equals(SAME_AS_SOURCE) || compressionLevel.equals(NO_COMPRESSION) || entry.getUncompressedSize() < LARGE_ENTRY_SIZE_THRESHOLD_BYTES) {
                sources.add(immediateFuture(sourceFactory.create(entry, compressionLevel)));
            } else {
                sources.add(executor.submit(() -> sourceFactory.create(entry, compressionLevel)));
            }
        }
        // as they're ready.
        for (ListenableFuture<ZipEntrySource> sourceFuture : Futures.inCompletionOrder(sources)) {
            ZipEntrySource source = Futures.getUnchecked(sourceFuture);
            if (source.getCompressionLevel().isCompressed() && source.getCompressedSize() >= source.getUncompressedSize()) {
                // No benefit in compressing, leave the file uncompressed.
                newBundle.add(sourceFactory.create(source.getEntry(), NO_COMPRESSION));
            } else {
                newBundle.add(source);
            }
        }
    } catch (IOException e) {
        throw new UncheckedIOException(e);
    }
}
Also used : ArrayList(java.util.ArrayList) ZipArchive(com.android.zipflinger.ZipArchive) ZipReader(com.android.tools.build.bundletool.io.ZipReader) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) ZipEntrySourceFactory(com.android.tools.build.bundletool.io.ZipEntrySourceFactory) TempDirectory(com.android.tools.build.bundletool.io.TempDirectory) BundleConfig(com.android.bundle.Config.BundleConfig) Entry(com.android.zipflinger.Entry) CompressionLevel(com.android.tools.build.bundletool.model.CompressionLevel) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) ZipEntrySource(com.android.tools.build.bundletool.io.ZipEntrySource)

Aggregations

BundleConfig (com.android.bundle.Config.BundleConfig)11 AppBundle (com.android.tools.build.bundletool.model.AppBundle)5 ZipPath (com.android.tools.build.bundletool.model.ZipPath)5 ImmutableList (com.google.common.collect.ImmutableList)5 IOException (java.io.IOException)5 UncheckedIOException (java.io.UncheckedIOException)5 BundleModule (com.android.tools.build.bundletool.model.BundleModule)4 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)4 ZipFile (java.util.zip.ZipFile)4 ModuleEntry (com.android.tools.build.bundletool.model.ModuleEntry)3 Path (java.nio.file.Path)3 BundleModuleName (com.android.tools.build.bundletool.model.BundleModuleName)2 ZipUtils (com.android.tools.build.bundletool.model.utils.ZipUtils)2 Version (com.android.tools.build.bundletool.model.version.Version)2 Entry (com.android.zipflinger.Entry)2 ZipArchive (com.android.zipflinger.ZipArchive)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)2 Predicates.not (com.google.common.base.Predicates.not)2 ListenableFuture (com.google.common.util.concurrent.ListenableFuture)2 ZipEntry (java.util.zip.ZipEntry)2