Search in sources :

Example 1 with BundleModuleName

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

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

the class DumpCommand method execute.

public void execute() {
    validateInput();
    switch(getDumpTarget()) {
        case CONFIG:
            new DumpManager(getOutputStream(), getBundlePath()).printBundleConfig();
            break;
        case MANIFEST:
            BundleModuleName moduleName = getModuleName().map(BundleModuleName::create).orElse(BundleModuleName.BASE_MODULE_NAME);
            new DumpManager(getOutputStream(), getBundlePath()).printManifest(moduleName, getXPathExpression());
            break;
        case RESOURCES:
            new DumpManager(getOutputStream(), getBundlePath()).printResources(parseResourcePredicate(), getPrintValues().orElse(false));
            break;
    }
}
Also used : BundleModuleName(com.android.tools.build.bundletool.model.BundleModuleName)

Example 3 with BundleModuleName

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

the class BundleModulesValidator method toBundleModule.

private BundleModule toBundleModule(ZipFile moduleZipFile, BundleConfig bundleConfig) {
    BundleModule bundleModule = BundleModule.builder().setName(BundleModuleName.create("TEMPORARY_MODULE_NAME")).setBundleConfig(bundleConfig).addEntries(moduleZipFile.stream().filter(not(ZipEntry::isDirectory)).map(zipEntry -> ModuleEntry.builder().setPath(ZipPath.create(zipEntry.getName())).setContent(ZipUtils.asByteSource(moduleZipFile, zipEntry)).build()).collect(toImmutableList())).build();
    BundleModuleName actualModuleName = bundleModule.getAndroidManifest().getSplitId().map(BundleModuleName::create).orElse(BundleModuleName.BASE_MODULE_NAME);
    return bundleModule.toBuilder().setName(actualModuleName).build();
}
Also used : BundleModuleName(com.android.tools.build.bundletool.model.BundleModuleName) ZipPath(com.android.tools.build.bundletool.model.ZipPath) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Predicates.not(com.google.common.base.Predicates.not) ImmutableList(com.google.common.collect.ImmutableList) BundleConfig(com.android.bundle.Config.BundleConfig) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) ZipFile(java.util.zip.ZipFile) VisibleForTesting(com.google.common.annotations.VisibleForTesting) AppBundle(com.android.tools.build.bundletool.model.AppBundle) BundleModule(com.android.tools.build.bundletool.model.BundleModule) ZipUtils(com.android.tools.build.bundletool.model.utils.ZipUtils) ZipEntry(java.util.zip.ZipEntry) BundleModuleName(com.android.tools.build.bundletool.model.BundleModuleName) BundleModule(com.android.tools.build.bundletool.model.BundleModule)

Example 4 with BundleModuleName

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

the class SystemApksGenerator method processSplitsOfSystemShard.

private ImmutableList<ModuleSplit> processSplitsOfSystemShard(ImmutableList<ModuleSplit> splits, ImmutableSet<BundleModuleName> modulesToFuse) {
    ImmutableSet<ModuleSplit> splitsOfFusedModules = splits.stream().filter(module -> modulesToFuse.contains(module.getModuleName())).collect(toImmutableSet());
    ImmutableSet<ModuleSplit> splitsOfNonFusedModules = Sets.difference(ImmutableSet.copyOf(splits), splitsOfFusedModules).immutableCopy();
    ImmutableSet<ModuleSplit> splitsWithOnlyDeviceLanguages = filterOutUnusedLanguageSplits(splitsOfFusedModules);
    ModuleSplit systemSplit = mergeSplitsToSystemApk(splitsWithOnlyDeviceLanguages);
    AndroidManifest systemSplitManifest = systemSplit.getAndroidManifest();
    // Groups all the unmatched language splits for fused modules by language and fuse them to
    // generate a single split for each language.
    ImmutableSet<ModuleSplit> additionalLanguageSplits = Sets.difference(splitsOfFusedModules, splitsWithOnlyDeviceLanguages).stream().collect(groupingByDeterministic(ModuleSplit::getApkTargeting)).values().stream().map(splitsPerLanguage -> mergeLanguageSplitsIntoOne(splitsPerLanguage, systemSplitManifest)).collect(toImmutableSet());
    // Write split id and variant targeting for splits that are not fused.
    ImmutableList<ModuleSplit> additionalSplits = Sets.union(additionalLanguageSplits, splitsOfNonFusedModules).stream().collect(groupingByDeterministic(ModuleSplit::getModuleName)).values().stream().flatMap(SystemApksGenerator::writeSplitIdInManifestHavingSameModule).map(module -> writeSplitTargetingAndSplitTypeToAdditionalSplit(module, systemSplit.getVariantTargeting())).collect(toImmutableList());
    return ImmutableList.<ModuleSplit>builder().add(systemSplit).addAll(additionalSplits).build();
}
Also used : Iterables(com.google.common.collect.Iterables) AndroidManifestMerger.manifestOverride(com.android.tools.build.bundletool.mergers.AndroidManifestMerger.manifestOverride) BundleModuleName(com.android.tools.build.bundletool.model.BundleModuleName) SuffixManager(com.android.tools.build.bundletool.model.SuffixManager) ZipPath(com.android.tools.build.bundletool.model.ZipPath) AndroidManifest(com.android.tools.build.bundletool.model.AndroidManifest) HashMap(java.util.HashMap) DeviceSpec(com.android.bundle.Devices.DeviceSpec) CollectorUtils.groupingByDeterministic(com.android.tools.build.bundletool.model.utils.CollectorUtils.groupingByDeterministic) CodeTransparencyInjector(com.android.tools.build.bundletool.splitters.CodeTransparencyInjector) Inject(javax.inject.Inject) ImmutableList(com.google.common.collect.ImmutableList) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) ApkMatcher(com.android.tools.build.bundletool.device.ApkMatcher) TargetingUtils.standaloneApkVariantTargeting(com.android.tools.build.bundletool.model.targeting.TargetingUtils.standaloneApkVariantTargeting) VariantTargeting(com.android.bundle.Targeting.VariantTargeting) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ApkOptimizations(com.android.tools.build.bundletool.optimizations.ApkOptimizations) SplitType(com.android.tools.build.bundletool.model.ModuleSplit.SplitType) Maps(com.google.common.collect.Maps) Sets(com.google.common.collect.Sets) Preconditions.checkState(com.google.common.base.Preconditions.checkState) ModuleSplitsToShardMerger(com.android.tools.build.bundletool.mergers.ModuleSplitsToShardMerger) Stream(java.util.stream.Stream) ModuleSplit(com.android.tools.build.bundletool.model.ModuleSplit) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) Optional(java.util.Optional) AppBundle(com.android.tools.build.bundletool.model.AppBundle) BundleModule(com.android.tools.build.bundletool.model.BundleModule) ModuleSplit(com.android.tools.build.bundletool.model.ModuleSplit) AndroidManifest(com.android.tools.build.bundletool.model.AndroidManifest)

Example 5 with BundleModuleName

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

the class ModuleNamesValidator method validateAllModules.

@Override
public void validateAllModules(ImmutableList<BundleModule> modules) {
    Set<BundleModuleName> moduleNames = new HashSet<>();
    for (BundleModule module : modules) {
        Optional<String> splitId = module.getAndroidManifest().getSplitId();
        BundleModuleName moduleName = module.getName();
        boolean isFeatureModule = module.getAndroidManifest().getModuleType().isFeatureModule();
        if (moduleName.equals(BundleModuleName.BASE_MODULE_NAME)) {
            if (splitId.isPresent()) {
                throw InvalidBundleException.builder().withUserMessage("The base module should not have the 'split' attribute set in the " + "AndroidManifest.xml").build();
            }
        } else {
            if (splitId.isPresent()) {
                if (!splitId.get().equals(moduleName.getName())) {
                    throw InvalidBundleException.builder().withUserMessage("The 'split' attribute in the AndroidManifest.xml of modules must be the name " + "of the module, but has the value '%s' in module '%s'", splitId.get(), moduleName).build();
                }
            } else {
                throw InvalidBundleException.builder().withUserMessage("No 'split' attribute found in the AndroidManifest.xml of module '%s'.", moduleName).build();
            }
        }
        boolean alreadyPresent = !moduleNames.add(moduleName);
        if (alreadyPresent) {
            if (splitId.isPresent()) {
                throw InvalidBundleException.builder().withUserMessage("More than one module have the 'split' attribute set to '%s' in the " + "AndroidManifest.xml.", splitId.get()).build();
            } else if (isFeatureModule) {
                throw InvalidBundleException.builder().withUserMessage("More than one module was found without the 'split' attribute set in the" + " AndroidManifest.xml. Ensure that all the dynamic features have the" + " 'split' attribute correctly set in the AndroidManifest.xml.").build();
            }
        }
    }
    if (!BundleValidationUtils.isAssetOnlyBundle(modules) && !moduleNames.contains(BundleModuleName.BASE_MODULE_NAME)) {
        throw InvalidBundleException.builder().withUserMessage("No base module found. At least one module must not have a 'split' attribute set in" + " the AndroidManifest.xml.").build();
    }
}
Also used : BundleModuleName(com.android.tools.build.bundletool.model.BundleModuleName) HashSet(java.util.HashSet) BundleModule(com.android.tools.build.bundletool.model.BundleModule)

Aggregations

BundleModuleName (com.android.tools.build.bundletool.model.BundleModuleName)26 AndroidManifest (com.android.tools.build.bundletool.model.AndroidManifest)19 Test (org.junit.Test)14 ZipPath (com.android.tools.build.bundletool.model.ZipPath)6 BundleModule (com.android.tools.build.bundletool.model.BundleModule)5 ModuleSplit (com.android.tools.build.bundletool.model.ModuleSplit)5 ImmutableList (com.google.common.collect.ImmutableList)5 AppBundle (com.android.tools.build.bundletool.model.AppBundle)4 ModuleEntry (com.android.tools.build.bundletool.model.ModuleEntry)4 HashMap (java.util.HashMap)4 BundleConfig (com.android.bundle.Config.BundleConfig)3 VariantTargeting (com.android.bundle.Targeting.VariantTargeting)3 CommandExecutionException (com.android.tools.build.bundletool.model.exceptions.CommandExecutionException)3 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)3 ResourceTable (com.android.aapt.Resources.ResourceTable)2 DeviceSpec (com.android.bundle.Devices.DeviceSpec)2 TargetedAssetsDirectory (com.android.bundle.Files.TargetedAssetsDirectory)2 Predicates.not (com.google.common.base.Predicates.not)2 ImmutableMap (com.google.common.collect.ImmutableMap)2 ImmutableMap.toImmutableMap (com.google.common.collect.ImmutableMap.toImmutableMap)2