Search in sources :

Example 1 with AppBundle

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

the class BuildApksCommand method execute.

public Path execute() {
    validateInput();
    Path outputDirectory = getOutputFormat().equals(APK_SET) ? getOutputFile().getParent() : getOutputFile();
    if (outputDirectory != null && Files.notExists(outputDirectory)) {
        logger.info("Output directory '" + outputDirectory + "' does not exist, creating it.");
        FileUtils.createDirectories(outputDirectory);
    }
    try (TempDirectory tempDir = new TempDirectory(getClass().getSimpleName())) {
        Path bundlePath;
        // The old APK serializer relies on the compression of entries in the App Bundle.
        // Unfortunately, we don't know the compression level that was used when the bundle was built,
        // so we re-compress all entries with our desired compression level.
        // Exception is made when the device spec is specified, we only need a fraction of the
        // entries, so re-compressing all entries would be a waste of CPU.
        boolean recompressAppBundle = !getDeviceSpec().isPresent() && !getEnableApkSerializerWithoutBundleRecompression();
        if (recompressAppBundle) {
            bundlePath = tempDir.getPath().resolve("recompressed.aab");
            new AppBundleRecompressor(getExecutorService()).recompressAppBundle(getBundlePath().toFile(), bundlePath.toFile());
        } else {
            bundlePath = getBundlePath();
        }
        try (ZipFile bundleZip = new ZipFile(bundlePath.toFile());
            ZipReader zipReader = ZipReader.createFromFile(bundlePath);
            Closer closer = Closer.create()) {
            AppBundleValidator bundleValidator = AppBundleValidator.create(getExtraValidators());
            bundleValidator.validateFile(bundleZip);
            AppBundle appBundle = AppBundle.buildFromZip(bundleZip);
            bundleValidator.validate(appBundle);
            validateSdkBundles(closer);
            AppBundlePreprocessorManager appBundlePreprocessorManager = DaggerAppBundlePreprocessorComponent.builder().setBuildApksCommand(this).build().create();
            AppBundle preprocessedAppBundle = appBundlePreprocessorManager.processAppBundle(appBundle);
            BuildApksManager buildApksManager = DaggerBuildApksManagerComponent.builder().setBuildApksCommand(this).setTempDirectory(tempDir).setAppBundle(preprocessedAppBundle).setZipReader(zipReader).setUseBundleCompression(recompressAppBundle).build().create();
            buildApksManager.execute();
        } catch (ZipException e) {
            throw InvalidBundleException.builder().withCause(e).withUserMessage("The App Bundle is not a valid zip file.").build();
        } finally {
            if (isExecutorServiceCreatedByBundleTool()) {
                getExecutorService().shutdown();
            }
        }
    } catch (IOException e) {
        throw new UncheckedIOException("An error occurred when processing the App Bundle.", e);
    }
    return getOutputFile();
}
Also used : Path(java.nio.file.Path) Closer(com.google.common.io.Closer) AppBundleValidator(com.android.tools.build.bundletool.validation.AppBundleValidator) AppBundle(com.android.tools.build.bundletool.model.AppBundle) ZipReader(com.android.tools.build.bundletool.io.ZipReader) ZipException(java.util.zip.ZipException) UncheckedIOException(java.io.UncheckedIOException) AppBundlePreprocessorManager(com.android.tools.build.bundletool.preprocessors.AppBundlePreprocessorManager) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) TempDirectory(com.android.tools.build.bundletool.io.TempDirectory) AppBundleRecompressor(com.android.tools.build.bundletool.preprocessors.AppBundleRecompressor) ZipFile(java.util.zip.ZipFile)

Example 2 with AppBundle

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

the class BuildApksManager method execute.

public void execute() throws IOException {
    ImmutableSet<BundleModuleName> permanentlyFusedModules = ImmutableSet.of();
    ImmutableSet<BundleModule> requestedModules = command.getModules().isEmpty() ? ImmutableSet.of() : ModuleDependenciesUtils.getModulesIncludingDependencies(appBundle, getBundleModules(appBundle, command.getModules()));
    GeneratedApks.Builder generatedApksBuilder = GeneratedApks.builder();
    GeneratedAssetSlices.Builder generatedAssetSlices = GeneratedAssetSlices.builder();
    boolean enableUniversalAsFallbackForSplits = false;
    boolean enableInstallTimeNonRemovableModules = false;
    ApksToGenerate apksToGenerate = new ApksToGenerate(appBundle, command.getApkBuildMode(), enableUniversalAsFallbackForSplits, deviceSpec);
    // Split APKs
    if (apksToGenerate.generateSplitApks()) {
        AppBundle mergedAppBundle = BundleModuleMerger.mergeNonRemovableInstallTimeModules(appBundle, enableInstallTimeNonRemovableModules);
        AppBundleValidator bundleValidator = AppBundleValidator.create(command.getExtraValidators());
        bundleValidator.validate(mergedAppBundle);
        generatedApksBuilder.setSplitApks(generateSplitApks(mergedAppBundle));
        permanentlyFusedModules = Sets.difference(appBundle.getModules().keySet(), mergedAppBundle.getModules().keySet()).immutableCopy();
    }
    // Instant APKs
    if (apksToGenerate.generateInstantApks()) {
        generatedApksBuilder.setInstantApks(generateInstantApks(appBundle));
    }
    // Standalone APKs
    if (apksToGenerate.generateStandaloneApks()) {
        generatedApksBuilder.setStandaloneApks(generateStandaloneApks(appBundle));
    }
    // Universal APK
    if (apksToGenerate.generateUniversalApk()) {
        // Note: Universal APK is a special type of standalone, with no optimization dimensions.
        ImmutableList<BundleModule> modulesToFuse = requestedModules.isEmpty() ? modulesToFuse(getModulesForStandaloneApks(appBundle)) : requestedModules.asList();
        generatedApksBuilder.setStandaloneApks(shardedApksFacade.generateSplits(modulesToFuse, ApkOptimizations.getOptimizationsForUniversalApk()));
    }
    // System APKs
    if (apksToGenerate.generateSystemApks()) {
        generatedApksBuilder.setSystemApks(generateSystemApks(appBundle, requestedModules));
    }
    // Archived APKs
    if (apksToGenerate.generateArchivedApks()) {
        generatedApksBuilder.setArchivedApks(generateArchivedApks(appBundle));
    }
    // Asset Slices
    if (apksToGenerate.generateAssetSlices()) {
        generatedAssetSlices.setAssetSlices(generateAssetSlices(appBundle));
    }
    // Populate alternative targeting based on variant targeting of all APKs.
    GeneratedApks generatedApks = AlternativeVariantTargetingPopulator.populateAlternativeVariantTargeting(generatedApksBuilder.build(), appBundle.isAssetOnly() ? Optional.empty() : appBundle.getBaseModule().getAndroidManifest().getMaxSdkVersion());
    // A variant is a set of APKs. One device is guaranteed to receive only APKs from the same. This
    // is why we are processing new entries like split.xml for each variant separately.
    generatedApks = GeneratedApks.fromModuleSplits(generatedApks.getAllApksGroupedByOrderedVariants().asMap().entrySet().stream().map(keySplit -> {
        SplitsXmlInjector splitsXmlInjector = new SplitsXmlInjector();
        ImmutableList<ModuleSplit> moduleSplits = splitsXmlInjector.process(keySplit.getKey(), keySplit.getValue());
        LocaleConfigXmlInjector localeConfigXmlInjector = new LocaleConfigXmlInjector();
        moduleSplits = localeConfigXmlInjector.process(keySplit.getKey(), moduleSplits);
        return moduleSplits;
    }).flatMap(Collection::stream).collect(toImmutableList()));
    if (deviceSpec.isPresent()) {
        // It is easier to fully check device compatibility once the splits have been generated (in
        // memory). Note that no costly I/O happened up until this point, so it's not too late for
        // this check.
        checkDeviceCompatibilityWithBundle(generatedApks, deviceSpec.get());
    }
    if (command.getOverwriteOutput() && Files.exists(command.getOutputFile())) {
        MoreFiles.deleteRecursively(command.getOutputFile(), RecursiveDeleteOption.ALLOW_INSECURE);
    }
    // Create variants and serialize APKs.
    apkSerializerManager.serializeApkSet(createApkSetWriter(tempDir.getPath()), generatedApks, generatedAssetSlices.build(), deviceSpec, getLocalTestingInfo(appBundle), permanentlyFusedModules);
}
Also used : BundleModuleName(com.android.tools.build.bundletool.model.BundleModuleName) AppBundle(com.android.tools.build.bundletool.model.AppBundle) AppBundleValidator(com.android.tools.build.bundletool.validation.AppBundleValidator) GeneratedApks(com.android.tools.build.bundletool.model.GeneratedApks) ModuleSplit(com.android.tools.build.bundletool.model.ModuleSplit) BundleModule(com.android.tools.build.bundletool.model.BundleModule) SplitsXmlInjector(com.android.tools.build.bundletool.model.utils.SplitsXmlInjector) GeneratedAssetSlices(com.android.tools.build.bundletool.model.GeneratedAssetSlices) LocaleConfigXmlInjector(com.android.tools.build.bundletool.model.utils.LocaleConfigXmlInjector)

Example 3 with AppBundle

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

the class BundleConfigValidatorTest method optimizations_tcfDimensionSuffixStrippingWithInvalidDefault_throws.

@Test
public void optimizations_tcfDimensionSuffixStrippingWithInvalidDefault_throws() throws Exception {
    AppBundle appBundle = createAppBundle(BundleConfigBuilder.create().clearOptimizations().addSplitDimension(SplitDimension.newBuilder().setValueValue(Value.TEXTURE_COMPRESSION_FORMAT_VALUE).setSuffixStripping(SuffixStripping.newBuilder().setEnabled(true).setDefaultSuffix("unrecognized_tcf")).build()));
    InvalidBundleException exception = assertThrows(InvalidBundleException.class, () -> new BundleConfigValidator().validateBundle(appBundle));
    assertThat(exception).hasMessageThat().contains("The default texture compression format chosen for suffix stripping" + " (\"unrecognized_tcf\") is not valid.");
}
Also used : AppBundle(com.android.tools.build.bundletool.model.AppBundle) InvalidBundleException(com.android.tools.build.bundletool.model.exceptions.InvalidBundleException) Test(org.junit.Test)

Example 4 with AppBundle

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

the class BundleConfigValidatorTest method optimizations_duplicateSplitDimensions_positiveAndNegative_throws.

@Test
public void optimizations_duplicateSplitDimensions_positiveAndNegative_throws() throws Exception {
    AppBundle appBundle = createAppBundle(BundleConfigBuilder.create().clearOptimizations().addSplitDimension(SplitDimension.Value.ABI, /* negate= */
    false).addSplitDimension(SplitDimension.Value.ABI, /* negate= */
    true));
    InvalidBundleException exception = assertThrows(InvalidBundleException.class, () -> new BundleConfigValidator().validateBundle(appBundle));
    assertThat(exception).hasMessageThat().contains("duplicate split dimensions");
}
Also used : AppBundle(com.android.tools.build.bundletool.model.AppBundle) InvalidBundleException(com.android.tools.build.bundletool.model.exceptions.InvalidBundleException) Test(org.junit.Test)

Example 5 with AppBundle

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

the class BundleConfigValidatorTest method optimizations_nonTcfDimensionsSuffixStrippingDisabled_ok.

@Test
public void optimizations_nonTcfDimensionsSuffixStrippingDisabled_ok() throws Exception {
    AppBundle appBundle = createAppBundle(BundleConfigBuilder.create().clearOptimizations().addSplitDimension(SplitDimension.newBuilder().setValueValue(Value.LANGUAGE_VALUE).setSuffixStripping(SuffixStripping.newBuilder().setEnabled(false)).build()));
    new BundleConfigValidator().validateBundle(appBundle);
}
Also used : AppBundle(com.android.tools.build.bundletool.model.AppBundle) Test(org.junit.Test)

Aggregations

AppBundle (com.android.tools.build.bundletool.model.AppBundle)205 Test (org.junit.Test)193 AppBundleBuilder (com.android.tools.build.bundletool.testing.AppBundleBuilder)137 ZipFile (java.util.zip.ZipFile)136 ManifestProtoUtils.androidManifest (com.android.tools.build.bundletool.testing.ManifestProtoUtils.androidManifest)112 Truth.assertThat (com.google.common.truth.Truth.assertThat)112 Path (java.nio.file.Path)112 RunWith (org.junit.runner.RunWith)112 BuildApksResult (com.android.bundle.Commands.BuildApksResult)106 AppBundleSerializer (com.android.tools.build.bundletool.io.AppBundleSerializer)104 ImmutableList (com.google.common.collect.ImmutableList)102 Assertions.assertThrows (org.junit.jupiter.api.Assertions.assertThrows)101 InvalidBundleException (com.android.tools.build.bundletool.model.exceptions.InvalidBundleException)100 Before (org.junit.Before)100 Rule (org.junit.Rule)100 TemporaryFolder (org.junit.rules.TemporaryFolder)100 Variant (com.android.bundle.Commands.Variant)98 IOException (java.io.IOException)94 ApkDescription (com.android.bundle.Commands.ApkDescription)90 ApkSetUtils.extractTocFromApkSetFile (com.android.tools.build.bundletool.testing.ApkSetUtils.extractTocFromApkSetFile)87