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);
}
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;
}
}
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();
}
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();
}
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();
}
}
Aggregations