Search in sources :

Example 6 with ZipPath

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

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

the class AssetsTargetingValidator method validateTargeting.

private void validateTargeting(BundleModule module, Assets assets) {
    ImmutableSet<ZipPath> assetDirsWithFiles = getDirectoriesWithFiles(module);
    for (TargetedAssetsDirectory targetedDirectory : assets.getDirectoryList()) {
        ZipPath path = ZipPath.create(targetedDirectory.getPath());
        if (!path.startsWith(ASSETS_DIRECTORY)) {
            throw InvalidBundleException.builder().withUserMessage("Path of targeted assets directory must start with 'assets/' but found '%s'.", path).build();
        }
        if (!assetDirsWithFiles.contains(path)) {
            throw InvalidBundleException.builder().withUserMessage("Targeted directory '%s' is empty.", path).build();
        }
        checkNoDimensionWithoutValuesAndAlternatives(targetedDirectory);
    }
    if (module.getModuleType().equals(ModuleType.ASSET_MODULE) && assets.getDirectoryList().stream().anyMatch(dir -> dir.getTargeting().hasLanguage())) {
        throw InvalidBundleException.builder().withUserMessage("Language targeting for asset packs is not supported, but found in module %s.", module.getName().getName()).build();
    }
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) ZipPath(com.android.tools.build.bundletool.model.ZipPath) AssetsDirectoryTargeting(com.android.bundle.Targeting.AssetsDirectoryTargeting) InvalidBundleException(com.android.tools.build.bundletool.model.exceptions.InvalidBundleException) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) TargetedAssetsDirectory(com.android.bundle.Files.TargetedAssetsDirectory) ASSETS_DIRECTORY(com.android.tools.build.bundletool.model.BundleModule.ASSETS_DIRECTORY) Assets(com.android.bundle.Files.Assets) ModuleType(com.android.tools.build.bundletool.model.BundleModule.ModuleType) BundleValidationUtils.checkHasValuesOrAlternatives(com.android.tools.build.bundletool.validation.BundleValidationUtils.checkHasValuesOrAlternatives) BundleModule(com.android.tools.build.bundletool.model.BundleModule) TargetedAssetsDirectory(com.android.bundle.Files.TargetedAssetsDirectory) ZipPath(com.android.tools.build.bundletool.model.ZipPath)

Example 8 with ZipPath

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

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

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

the class ResourceAnalyzer method findAllReferencedAppResources.

private ImmutableSet<ResourceId> findAllReferencedAppResources(Item item) {
    switch(item.getValueCase()) {
        case REF:
            if (item.getRef().getId() != 0) {
                return ImmutableSet.of(ResourceId.create(item.getRef().getId()));
            }
            // we don't need to consider it.
            break;
        case FILE:
            FileReference fileRef = item.getFile();
            if (!fileRef.getType().equals(FileReference.Type.PROTO_XML)) {
                return ImmutableSet.of();
            }
            ZipPath xmlResourcePath = ZipPath.create(fileRef.getPath());
            try (InputStream is = appBundle.getBaseModule().getEntry(xmlResourcePath).get().getContent().openStream()) {
                XmlNode xmlRoot = XmlNode.parseFrom(is);
                return findAllReferencedAppResources(xmlRoot);
            } catch (InvalidProtocolBufferException e) {
                throw CommandExecutionException.builder().withInternalMessage("Error parsing XML file '%s'.", xmlResourcePath).withCause(e).build();
            } catch (IOException e) {
                throw new UncheckedIOException(String.format("Failed to parse file '%s' in base module.", xmlResourcePath), e);
            }
        default:
            break;
    }
    return ImmutableSet.of();
}
Also used : XmlNode(com.android.aapt.Resources.XmlNode) InputStream(java.io.InputStream) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) UncheckedIOException(java.io.UncheckedIOException) ZipPath(com.android.tools.build.bundletool.model.ZipPath) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) FileReference(com.android.aapt.Resources.FileReference)

Aggregations

ZipPath (com.android.tools.build.bundletool.model.ZipPath)194 Test (org.junit.Test)154 BuildApksResult (com.android.bundle.Commands.BuildApksResult)106 Path (java.nio.file.Path)55 DeviceSpec (com.android.bundle.Devices.DeviceSpec)44 InvalidBundleException (com.android.tools.build.bundletool.model.exceptions.InvalidBundleException)23 ImmutableSet (com.google.common.collect.ImmutableSet)23 ModuleEntry (com.android.tools.build.bundletool.model.ModuleEntry)19 Variant (com.android.bundle.Commands.Variant)16 ApksArchiveHelpers.createVariant (com.android.tools.build.bundletool.testing.ApksArchiveHelpers.createVariant)15 BundleModule (com.android.tools.build.bundletool.model.BundleModule)13 ImmutableList (com.google.common.collect.ImmutableList)12 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)11 ApksArchiveHelpers.standaloneVariant (com.android.tools.build.bundletool.testing.ApksArchiveHelpers.standaloneVariant)10 Theory (org.junit.experimental.theories.Theory)10 AdbServer (com.android.tools.build.bundletool.device.AdbServer)9 IOException (java.io.IOException)9 ModuleSplit (com.android.tools.build.bundletool.model.ModuleSplit)8 ImmutableSet.toImmutableSet (com.google.common.collect.ImmutableSet.toImmutableSet)8 UncheckedIOException (java.io.UncheckedIOException)8