Search in sources :

Example 1 with ModuleEntry

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

the class ApexBundleValidator method validateModule.

@Override
public void validateModule(BundleModule module) {
    if (module.findEntriesUnderPath(APEX_DIRECTORY).count() == 0) {
        return;
    }
    Optional<ModuleEntry> apexManifest = module.getEntry(APEX_MANIFEST_PATH);
    if (apexManifest.isPresent()) {
        validateApexManifest(apexManifest.get());
    } else {
        apexManifest = module.getEntry(APEX_MANIFEST_JSON_PATH);
        if (!apexManifest.isPresent()) {
            throw InvalidBundleException.builder().withUserMessage("Missing expected file in APEX bundle: '%s' or '%s'.", APEX_MANIFEST_PATH, APEX_MANIFEST_JSON_PATH).build();
        }
        validateApexManifestJson(apexManifest.get());
    }
    ImmutableSet.Builder<String> apexImagesBuilder = ImmutableSet.builder();
    ImmutableSet.Builder<String> apexBuildInfosBuilder = ImmutableSet.builder();
    ImmutableSet.Builder<String> apexFileNamesBuilder = ImmutableSet.builder();
    for (ModuleEntry entry : module.getEntries()) {
        ZipPath path = entry.getPath();
        if (path.startsWith(APEX_DIRECTORY)) {
            if (path.getFileName().toString().endsWith(BundleModule.APEX_IMAGE_SUFFIX)) {
                apexImagesBuilder.add(path.toString());
                apexFileNamesBuilder.add(path.getFileName().toString());
            } else if (path.getFileName().toString().endsWith(BundleModule.BUILD_INFO_SUFFIX)) {
                apexBuildInfosBuilder.add(path.toString());
            } else {
                throw InvalidBundleException.builder().withUserMessage("Unexpected file in apex directory of bundle: '%s'.", entry.getPath()).build();
            }
        } else if (!ALLOWED_APEX_FILES_OUTSIDE_APEX_DIRECTORY.contains(path)) {
            throw InvalidBundleException.builder().withUserMessage("Unexpected file in APEX bundle: '%s'.", entry.getPath()).build();
        }
    }
    ImmutableSet<String> apexBuildInfos = apexBuildInfosBuilder.build();
    ImmutableSet<String> apexImages = apexImagesBuilder.build();
    ImmutableSet<ImmutableSet<AbiName>> allAbiNameSets = apexFileNamesBuilder.build().stream().map(ApexBundleValidator::abiNamesFromFile).collect(toImmutableSet());
    if (allAbiNameSets.size() != apexImages.size()) {
        throw InvalidBundleException.builder().withUserMessage("Every APEX image file must target a unique set of architectures, " + "but found multiple files that target the same set of architectures.").build();
    }
    ImmutableSet<String> expectedImages = apexBuildInfos.stream().map(f -> f.replace(BundleModule.BUILD_INFO_SUFFIX, BundleModule.APEX_IMAGE_SUFFIX)).collect(toImmutableSet());
    if (!apexBuildInfos.isEmpty() && !expectedImages.equals(apexImages)) {
        throw InvalidBundleException.builder().withUserMessage("If APEX build info is provided then one must be provided for each APEX image file:\n" + " Expected %s\n" + " Found %s.", expectedImages, apexImages).build();
    }
    if (REQUIRED_ONE_OF_ABI_SETS.stream().anyMatch(one_of -> one_of.stream().noneMatch(allAbiNameSets::contains))) {
        throw InvalidBundleException.builder().withUserMessage("APEX bundle must contain one of %s.", Joiner.on(" and one of ").join(REQUIRED_ONE_OF_ABI_SETS)).build();
    }
    module.getApexConfig().ifPresent(targeting -> validateTargeting(apexImages, targeting));
}
Also used : AbiName(com.android.tools.build.bundletool.model.AbiName) JsonObject(com.google.gson.JsonObject) ApexManifest(com.android.apex.ApexManifestProto.ApexManifest) ZipPath(com.android.tools.build.bundletool.model.ZipPath) JsonParser(com.google.gson.JsonParser) ARMEABI_V7A(com.android.tools.build.bundletool.model.AbiName.ARMEABI_V7A) JsonElement(com.google.gson.JsonElement) TargetedApexImage(com.android.bundle.Files.TargetedApexImage) ImmutableList(com.google.common.collect.ImmutableList) ARM64_V8A(com.android.tools.build.bundletool.model.AbiName.ARM64_V8A) X86(com.android.tools.build.bundletool.model.AbiName.X86) X86_64(com.android.tools.build.bundletool.model.AbiName.X86_64) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) APEX_MANIFEST_JSON_PATH(com.android.tools.build.bundletool.model.BundleModule.APEX_MANIFEST_JSON_PATH) APEX_PUBKEY_PATH(com.android.tools.build.bundletool.model.BundleModule.APEX_PUBKEY_PATH) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) ABI_SPLITTER(com.android.tools.build.bundletool.model.BundleModule.ABI_SPLITTER) ImmutableSet(com.google.common.collect.ImmutableSet) UTF_8(java.nio.charset.StandardCharsets.UTF_8) InvalidBundleException(com.android.tools.build.bundletool.model.exceptions.InvalidBundleException) IOException(java.io.IOException) Sets(com.google.common.collect.Sets) UncheckedIOException(java.io.UncheckedIOException) ApexImages(com.android.bundle.Files.ApexImages) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) ExtensionRegistry(com.google.protobuf.ExtensionRegistry) Optional(java.util.Optional) BufferedReader(java.io.BufferedReader) APEX_DIRECTORY(com.android.tools.build.bundletool.model.BundleModule.APEX_DIRECTORY) APEX_NOTICE_PATH(com.android.tools.build.bundletool.model.BundleModule.APEX_NOTICE_PATH) BundleModule(com.android.tools.build.bundletool.model.BundleModule) APEX_MANIFEST_PATH(com.android.tools.build.bundletool.model.BundleModule.APEX_MANIFEST_PATH) Joiner(com.google.common.base.Joiner) InputStream(java.io.InputStream) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) ImmutableSet(com.google.common.collect.ImmutableSet) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) ZipPath(com.android.tools.build.bundletool.model.ZipPath)

Example 2 with ModuleEntry

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

the class SuffixStripper method removeAssetsTargeting.

/**
 * Updates the module to remove the specified targeting from the assets - both the directories in
 * assets config and the associated module entries having the specified targeting will be updated.
 */
public ModuleSplit removeAssetsTargeting(ModuleSplit moduleSplit) {
    if (!moduleSplit.getAssetsConfig().isPresent()) {
        return moduleSplit;
    }
    // Update the targeted assets directory and their associated entries.
    Assets assetsConfig = moduleSplit.getAssetsConfig().get();
    Assets.Builder updatedAssetsConfig = assetsConfig.toBuilder().clearDirectory();
    ImmutableList<ModuleEntry> updatedEntries = moduleSplit.getEntries();
    for (TargetedAssetsDirectory targetedAssetsDirectory : assetsConfig.getDirectoryList()) {
        TargetedAssetsDirectory updatedTargetedAssetsDirectory = removeAssetsTargetingFromDirectory(targetedAssetsDirectory);
        // Remove the targeting from the entries path.
        if (!updatedTargetedAssetsDirectory.equals(targetedAssetsDirectory)) {
            // Update the associated entries
            ZipPath directoryPath = ZipPath.create(targetedAssetsDirectory.getPath());
            updatedEntries = updatedEntries.stream().map(entry -> {
                if (entry.getPath().startsWith(directoryPath)) {
                    return removeTargetingFromEntry(entry);
                }
                return entry;
            }).collect(toImmutableList());
        }
        updatedAssetsConfig.addDirectory(updatedTargetedAssetsDirectory);
    }
    return moduleSplit.toBuilder().setEntries(updatedEntries).setAssetsConfig(updatedAssetsConfig.build()).build();
}
Also used : TargetedAssetsDirectory(com.android.bundle.Files.TargetedAssetsDirectory) Assets(com.android.bundle.Files.Assets) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) ZipPath(com.android.tools.build.bundletool.model.ZipPath)

Example 3 with ModuleEntry

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

the class SuffixStripper method excludeAssetsTargetingOtherValue.

/**
 * Updates the module to remove the specified targeting from the assets: both the assets in assets
 * config and the associated entries having the specified targeting will be updated.
 */
private ModuleSplit excludeAssetsTargetingOtherValue(ModuleSplit moduleSplit, String value) {
    if (!moduleSplit.getAssetsConfig().isPresent()) {
        return moduleSplit;
    }
    // Update the targeted assets directory and their associated entries.
    Assets assetsConfig = moduleSplit.getAssetsConfig().get();
    Assets.Builder updatedAssetsConfig = assetsConfig.toBuilder().clearDirectory();
    ImmutableList<ModuleEntry> updatedEntries = moduleSplit.getEntries();
    for (TargetedAssetsDirectory targetedAssetsDirectory : assetsConfig.getDirectoryList()) {
        ZipPath directoryPath = ZipPath.create(targetedAssetsDirectory.getPath());
        // Check if the directory is targeted at this dimension, but for another value.
        if (dimensionHandler.isDirectoryTargetingOtherValue(targetedAssetsDirectory, value)) {
            // Removed the associated entries if so.
            updatedEntries = updatedEntries.stream().filter(entry -> !entry.getPath().startsWith(directoryPath)).collect(toImmutableList());
        } else {
            // Keep the directory otherwise.
            updatedAssetsConfig.addDirectory(targetedAssetsDirectory);
        }
    }
    return moduleSplit.toBuilder().setEntries(updatedEntries).setAssetsConfig(updatedAssetsConfig.build()).build();
}
Also used : TargetedAssetsDirectory(com.android.bundle.Files.TargetedAssetsDirectory) Assets(com.android.bundle.Files.Assets) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) ZipPath(com.android.tools.build.bundletool.model.ZipPath)

Example 4 with ModuleEntry

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

the class AbiNativeLibrariesSplitter method split.

/**
 * Generates {@link ModuleSplit} objects dividing the native libraries by ABI.
 */
@Override
public ImmutableCollection<ModuleSplit> split(ModuleSplit moduleSplit) {
    if (!moduleSplit.getNativeConfig().isPresent()) {
        return ImmutableList.of(moduleSplit);
    }
    ImmutableList.Builder<ModuleSplit> splits = new ImmutableList.Builder<>();
    // Flatten all targeted directories.
    List<TargetedNativeDirectory> allTargetedDirectories = moduleSplit.getNativeConfig().get().getDirectoryList();
    // Currently we only support targeting via ABI, so grouping it by Targeting.equals() should be
    // enough.
    ImmutableMultimap<NativeDirectoryTargeting, TargetedNativeDirectory> targetingMap = Multimaps.index(allTargetedDirectories, TargetedNativeDirectory::getTargeting);
    // We need to know the exact set of ABIs that we will generate, to set alternatives correctly.
    ImmutableSet<Abi> abisToGenerate = targetingMap.keySet().stream().map(NativeDirectoryTargeting::getAbi).collect(toImmutableSet());
    // Any entries not claimed by the ABI splits will be returned in a separate split using the
    // original targeting.
    HashSet<ModuleEntry> leftOverEntries = new HashSet<>(moduleSplit.getEntries());
    for (NativeDirectoryTargeting targeting : targetingMap.keySet()) {
        ImmutableList<ModuleEntry> entriesList = targetingMap.get(targeting).stream().flatMap(directory -> moduleSplit.findEntriesUnderPath(directory.getPath())).collect(toImmutableList());
        ModuleSplit.Builder splitBuilder = moduleSplit.toBuilder().setApkTargeting(moduleSplit.getApkTargeting().toBuilder().setAbiTargeting(AbiTargeting.newBuilder().addValue(targeting.getAbi()).addAllAlternatives(Sets.difference(abisToGenerate, ImmutableSet.of(targeting.getAbi())))).build()).setMasterSplit(false).addMasterManifestMutator(withSplitsRequired(true)).setEntries(entriesList);
        splits.add(splitBuilder.build());
        leftOverEntries.removeAll(entriesList);
    }
    if (!leftOverEntries.isEmpty()) {
        splits.add(moduleSplit.toBuilder().setEntries(ImmutableList.copyOf(leftOverEntries)).build());
    }
    return splits.build();
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) AbiTargeting(com.android.bundle.Targeting.AbiTargeting) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ImmutableCollection(com.google.common.collect.ImmutableCollection) Sets(com.google.common.collect.Sets) Multimaps(com.google.common.collect.Multimaps) HashSet(java.util.HashSet) ManifestMutator.withSplitsRequired(com.android.tools.build.bundletool.model.ManifestMutator.withSplitsRequired) List(java.util.List) ModuleSplit(com.android.tools.build.bundletool.model.ModuleSplit) ImmutableList(com.google.common.collect.ImmutableList) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) TargetedNativeDirectory(com.android.bundle.Files.TargetedNativeDirectory) ImmutableMultimap(com.google.common.collect.ImmutableMultimap) NativeDirectoryTargeting(com.android.bundle.Targeting.NativeDirectoryTargeting) Abi(com.android.bundle.Targeting.Abi) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ImmutableList(com.google.common.collect.ImmutableList) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) ModuleSplit(com.android.tools.build.bundletool.model.ModuleSplit) Abi(com.android.bundle.Targeting.Abi) NativeDirectoryTargeting(com.android.bundle.Targeting.NativeDirectoryTargeting) TargetedNativeDirectory(com.android.bundle.Files.TargetedNativeDirectory) HashSet(java.util.HashSet)

Example 5 with ModuleEntry

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

the class SanitizerNativeLibrariesSplitter method split.

/**
 * Generates {@link ModuleSplit} objects dividing the native libraries by sanitizer.
 */
@Override
public ImmutableCollection<ModuleSplit> split(ModuleSplit moduleSplit) {
    if (!moduleSplit.getNativeConfig().isPresent()) {
        return ImmutableList.of(moduleSplit);
    }
    Set<ZipPath> hwasanDirs = new HashSet<>();
    for (TargetedNativeDirectory dir : moduleSplit.getNativeConfig().get().getDirectoryList()) {
        if (!dir.getTargeting().hasSanitizer()) {
            continue;
        }
        if (dir.getTargeting().getSanitizer().getAlias().equals(SanitizerAlias.HWADDRESS)) {
            hwasanDirs.add(ZipPath.create(dir.getPath()));
        }
    }
    List<ModuleEntry> hwasanEntries = moduleSplit.getEntries().stream().filter(entry -> hwasanDirs.contains(entry.getPath().subpath(0, 2))).collect(toImmutableList());
    if (hwasanEntries.isEmpty()) {
        return ImmutableList.of(moduleSplit);
    }
    List<ModuleEntry> nonHwasanEntries = moduleSplit.getEntries().stream().filter(entry -> !hwasanDirs.contains(entry.getPath().subpath(0, 2))).collect(toImmutableList());
    ModuleSplit hwasanSplit = moduleSplit.toBuilder().setApkTargeting(moduleSplit.getApkTargeting().toBuilder().setSanitizerTargeting(SanitizerTargeting.newBuilder().addValue(Sanitizer.newBuilder().setAlias(SanitizerAlias.HWADDRESS))).build()).setMasterSplit(false).setEntries(hwasanEntries).build();
    ModuleSplit nonHwasanSplit = moduleSplit.toBuilder().setEntries(nonHwasanEntries).build();
    return ImmutableList.of(hwasanSplit, nonHwasanSplit);
}
Also used : ZipPath(com.android.tools.build.bundletool.model.ZipPath) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Sanitizer(com.android.bundle.Targeting.Sanitizer) ImmutableCollection(com.google.common.collect.ImmutableCollection) Set(java.util.Set) SanitizerTargeting(com.android.bundle.Targeting.SanitizerTargeting) HashSet(java.util.HashSet) List(java.util.List) SanitizerAlias(com.android.bundle.Targeting.Sanitizer.SanitizerAlias) ModuleSplit(com.android.tools.build.bundletool.model.ModuleSplit) ImmutableList(com.google.common.collect.ImmutableList) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) TargetedNativeDirectory(com.android.bundle.Files.TargetedNativeDirectory) TargetedNativeDirectory(com.android.bundle.Files.TargetedNativeDirectory) ModuleEntry(com.android.tools.build.bundletool.model.ModuleEntry) ModuleSplit(com.android.tools.build.bundletool.model.ModuleSplit) ZipPath(com.android.tools.build.bundletool.model.ZipPath) HashSet(java.util.HashSet)

Aggregations

ModuleEntry (com.android.tools.build.bundletool.model.ModuleEntry)41 ModuleSplit (com.android.tools.build.bundletool.model.ModuleSplit)22 ZipPath (com.android.tools.build.bundletool.model.ZipPath)18 ImmutableList (com.google.common.collect.ImmutableList)18 Test (org.junit.Test)13 BundleModule (com.android.tools.build.bundletool.model.BundleModule)12 ImmutableSet (com.google.common.collect.ImmutableSet)12 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)10 SpecialModuleEntry (com.android.tools.build.bundletool.model.BundleModule.SpecialModuleEntry)8 BundleModuleBuilder (com.android.tools.build.bundletool.testing.BundleModuleBuilder)6 HashMap (java.util.HashMap)6 Optional (java.util.Optional)6 TargetedAssetsDirectory (com.android.bundle.Files.TargetedAssetsDirectory)5 ImmutableSet.toImmutableSet (com.google.common.collect.ImmutableSet.toImmutableSet)5 IOException (java.io.IOException)5 Map (java.util.Map)5 ResourceTable (com.android.aapt.Resources.ResourceTable)4 ApkTargeting (com.android.bundle.Targeting.ApkTargeting)4 BundleModuleName (com.android.tools.build.bundletool.model.BundleModuleName)4 ApkOptimizations (com.android.tools.build.bundletool.optimizations.ApkOptimizations)4