Skip to content

Commit

Permalink
Prepare for release 0.10.3.
Browse files Browse the repository at this point in the history
  • Loading branch information
Hitish Chappidi committed Sep 17, 2019
1 parent 2e9ac4e commit 131c1fb
Show file tree
Hide file tree
Showing 26 changed files with 632 additions and 172 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ https://developer.android.com/studio/command-line/bundletool

## Releases

Latest release: [0.10.2](https://github.com/google/bundletool/releases)
Latest release: [0.10.3](https://github.com/google/bundletool/releases)
10 changes: 5 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ configurations {

// The repackaging rules are defined in the "shadowJar" task below.
dependencies {
compile "com.android.tools:r8:1.0.37"
compile "com.android.tools:r8:1.5.68"
compile "com.android.tools.build:apkzlib:3.4.0-beta01"
compile "com.android.tools.ddms:ddmlib:26.2.0"

shadow "com.android.tools.build:aapt2-proto:0.4.0"
shadow "com.google.auto.value:auto-value:1.5.2"
annotationProcessor "com.google.auto.value:auto-value:1.5.2"
shadow "com.google.auto.value:auto-value-annotations:1.6.2"
annotationProcessor "com.google.auto.value:auto-value:1.6.2"
shadow "com.google.errorprone:error_prone_annotations:2.3.1"
shadow "com.google.guava:guava:27.0.1-jre"
shadow "com.google.protobuf:protobuf-java:3.4.0"
Expand All @@ -49,8 +49,8 @@ dependencies {
compileLinux "com.android.tools.build:aapt2:3.5.0-alpha03-5252756:linux"

testCompile "com.android.tools.build:aapt2-proto:0.4.0"
testCompile "com.google.auto.value:auto-value-annotations:1.5.2"
testAnnotationProcessor "com.google.auto.value:auto-value:1.5.2"
testCompile "com.google.auto.value:auto-value-annotations:1.6.2"
testAnnotationProcessor "com.google.auto.value:auto-value:1.6.2"
testCompile "com.google.errorprone:error_prone_annotations:2.3.1"
testCompile "com.google.guava:guava:27.0.1-jre"
testCompile "com.google.truth.extensions:truth-java8-extension:0.45"
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
release_version = 0.10.2
release_version = 0.10.3
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-bin.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;

import com.android.bundle.Commands.AssetModuleMetadata;
import com.android.bundle.Commands.AssetSliceSet;
import com.android.bundle.Commands.BuildApksResult;
import com.android.bundle.Commands.DeliveryType;
import com.android.bundle.Devices.DeviceSpec;
import com.android.tools.build.bundletool.commands.CommandHelp.CommandDescription;
import com.android.tools.build.bundletool.commands.CommandHelp.FlagDescription;
Expand Down Expand Up @@ -52,6 +55,7 @@
import java.nio.file.Path;
import java.util.Optional;
import java.util.logging.Logger;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

Expand Down Expand Up @@ -169,11 +173,22 @@ ImmutableList<Path> execute(PrintStream output) {
.map(
modules ->
modules.contains(ALL_MODULES_SHORTCUT)
? toc.getVariantList().stream()
.flatMap(variant -> variant.getApkSetList().stream())
.map(apkSet -> apkSet.getModuleMetadata().getName())
? Stream.concat(
toc.getVariantList().stream()
.flatMap(variant -> variant.getApkSetList().stream())
.map(apkSet -> apkSet.getModuleMetadata().getName()),
toc.getAssetSliceSetList().stream()
.filter(
sliceSet ->
sliceSet
.getAssetModuleMetadata()
.getDeliveryType()
.equals(DeliveryType.INSTALL_TIME))
.map(AssetSliceSet::getAssetModuleMetadata)
.map(AssetModuleMetadata::getName))
.collect(toImmutableSet())
: modules);
validateAssetModules(toc, requestedModuleNames);

ApkMatcher apkMatcher = new ApkMatcher(getDeviceSpec(), requestedModuleNames, getInstant());
ImmutableList<ZipPath> matchedApks = apkMatcher.getMatchingApks(toc);
Expand Down Expand Up @@ -208,6 +223,33 @@ private void validateInput() {
}
}

/** Check that none of the requested modules is an asset module that is not install-time. */
private static void validateAssetModules(
BuildApksResult toc, Optional<ImmutableSet<String>> requestedModuleNames) {
if (requestedModuleNames.isPresent()) {
ImmutableList<String> requestedNonInstallTimeAssetModules =
toc.getAssetSliceSetList().stream()
.filter(
sliceSet ->
!sliceSet
.getAssetModuleMetadata()
.getDeliveryType()
.equals(DeliveryType.INSTALL_TIME))
.map(AssetSliceSet::getAssetModuleMetadata)
.map(AssetModuleMetadata::getName)
.filter(requestedModuleNames.get()::contains)
.collect(toImmutableList());
if (!requestedNonInstallTimeAssetModules.isEmpty()) {
throw ValidationException.builder()
.withMessage(
String.format(
"The following requested asset packs do not have install time delivery: %s.",
requestedNonInstallTimeAssetModules))
.build();
}
}
}

private ImmutableList<Path> extractMatchedApksFromApksArchive(
ImmutableList<ZipPath> matchedApkPaths) {
Path outputDirectoryPath =
Expand Down Expand Up @@ -295,10 +337,10 @@ public static CommandHelp help() {
.setExampleValue("base,module1,module2")
.setOptional(true)
.setDescription(
"List of modules to be extracted, or \"%s\" for all modules. Defaults to "
+ "modules installed during the first install, i.e. not on-demand. Note "
+ "that the dependent modules will also be extracted. The value of this "
+ "flag is ignored if the device receives a standalone APK.",
"List of modules to be extracted, or \"%s\" for all modules. "
+ "Defaults to modules installed during the first install, i.e. not "
+ "on-demand. Note that the dependent modules will also be extracted. The "
+ "value of this flag is ignored if the device receives a standalone APK.",
ALL_MODULES_SHORTCUT)
.build())
.addFlag(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,10 @@ public static CommandHelp help() {
.setExampleValue("base,module1,module2")
.setOptional(true)
.setDescription(
"List of modules to be installed, or \"%s\" for all modules. Defaults to "
+ "modules installed during first install, i.e. not on-demand. Note that "
+ "the dependent modules will also be installed. The value of this flag is "
+ "ignored if the device receives a standalone APK.",
"List of modules to be installed, or \"%s\" for all modules. "
+ "Defaults to modules installed during the first install, i.e. not "
+ "on-demand. Note that the dependent modules will also be extracted. The "
+ "value of this flag is ignored if the device receives a standalone APK.",
ExtractApksCommand.ALL_MODULES_SHORTCUT)
.build())
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,10 @@ private void printBundleSummary(AppBundle appBundle) {
printModuleSummary(moduleEntry.getValue());
}
if (!appBundle.getAssetModules().isEmpty()) {
System.out.printf("Remote asset modules:\n");
System.out.printf("Asset packs:\n");
for (Entry<BundleModuleName, BundleModule> moduleEntry :
appBundle.getAssetModules().entrySet()) {
System.out.printf("\tRemote asset module: %s\n", moduleEntry.getKey());
System.out.printf("\tAsset pack: %s\n", moduleEntry.getKey());
printModuleSummary(moduleEntry.getValue());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

import com.android.bundle.Commands.ApkDescription;
import com.android.bundle.Commands.ApkSet;
import com.android.bundle.Commands.AssetModuleMetadata;
import com.android.bundle.Commands.AssetSliceSet;
import com.android.bundle.Commands.BuildApksResult;
import com.android.bundle.Commands.DeliveryType;
import com.android.bundle.Commands.ModuleMetadata;
Expand Down Expand Up @@ -96,10 +98,19 @@ public ApkMatcher(
public ImmutableList<ZipPath> getMatchingApks(BuildApksResult buildApksResult) {
Optional<Variant> matchingVariant = variantMatcher.getMatchingVariant(buildApksResult);

return matchingVariant.isPresent()
? getMatchingApksFromVariant(
matchingVariant.get(), Version.of(buildApksResult.getBundletool().getVersion()))
: ImmutableList.of();
if (matchingVariant.isPresent()) {
validateVariant(matchingVariant.get(), buildApksResult);
}

ImmutableList<ZipPath> variantApks =
matchingVariant.isPresent()
? getMatchingApksFromVariant(
matchingVariant.get(), Version.of(buildApksResult.getBundletool().getVersion()))
: ImmutableList.of();

ImmutableList<ZipPath> assetModuleApks = getMatchingApksFromAssetModules(buildApksResult);

return ImmutableList.<ZipPath>builder().addAll(variantApks).addAll(assetModuleApks).build();
}

public ImmutableList<ZipPath> getMatchingApksFromVariant(Variant variant, Version bundleVersion) {
Expand Down Expand Up @@ -128,8 +139,6 @@ public ImmutableList<ZipPath> getMatchingApksFromVariant(Variant variant, Versio

private Predicate<String> getModuleNameMatcher(Variant variant, Version bundleVersion) {
if (requestedModuleNames.isPresent()) {
validateVariant(variant);

ImmutableMultimap<String, String> moduleDependenciesMap = buildAdjacencyMap(variant);

HashSet<String> dependencyModules = new HashSet<>(requestedModuleNames.get());
Expand All @@ -155,15 +164,19 @@ private Predicate<String> getModuleNameMatcher(Variant variant, Version bundleVe
}
}

private void validateVariant(Variant variant) {
private void validateVariant(Variant variant, BuildApksResult buildApksResult) {
if (requestedModuleNames.isPresent()) {
Set<String> unknownModules =
Sets.difference(
requestedModuleNames.get(),
Set<String> availableModules =
Sets.union(
variant.getApkSetList().stream()
.map(ApkSet::getModuleMetadata)
.map(ModuleMetadata::getName)
.collect(toImmutableSet()),
buildApksResult.getAssetSliceSetList().stream()
.map(AssetSliceSet::getAssetModuleMetadata)
.map(AssetModuleMetadata::getName)
.collect(toImmutableSet()));
Set<String> unknownModules = Sets.difference(requestedModuleNames.get(), availableModules);
if (!unknownModules.isEmpty()) {
throw ValidationException.builder()
.withMessage(
Expand Down Expand Up @@ -251,4 +264,42 @@ private <T> void checkCompatibleWithApkTargetingHelper(
TargetingDimensionMatcher<T> matcher, ApkTargeting apkTargeting) {
matcher.checkDeviceCompatible(matcher.getTargetingValue(apkTargeting));
}

private ImmutableList<ZipPath> getMatchingApksFromAssetModules(BuildApksResult buildApksResult) {
ImmutableList.Builder<ZipPath> matchedApksBuilder = ImmutableList.builder();

Predicate<String> assetModuleNameMatcher =
getInstallTimeAssetModuleNameMatcher(buildApksResult);

for (AssetSliceSet sliceSet : buildApksResult.getAssetSliceSetList()) {
String moduleName = sliceSet.getAssetModuleMetadata().getName();
for (ApkDescription apkDescription : sliceSet.getApkDescriptionList()) {
ApkTargeting apkTargeting = apkDescription.getTargeting();

checkCompatibleWithApkTargeting(apkTargeting);

if (matchesApk(apkTargeting, /*isSplit=*/ true, moduleName, assetModuleNameMatcher)) {
matchedApksBuilder.add(ZipPath.create(apkDescription.getPath()));
}
}
}
return matchedApksBuilder.build();
}

private Predicate<String> getInstallTimeAssetModuleNameMatcher(BuildApksResult buildApksResult) {
ImmutableSet<String> upfrontAssetModuleNames =
buildApksResult.getAssetSliceSetList().stream()
.filter(
sliceSet ->
sliceSet
.getAssetModuleMetadata()
.getDeliveryType()
.equals(DeliveryType.INSTALL_TIME))
.map(sliceSet -> sliceSet.getAssetModuleMetadata().getName())
.collect(toImmutableSet());

return requestedModuleNames.isPresent()
? Sets.intersection(upfrontAssetModuleNames, requestedModuleNames.get())::contains
: upfrontAssetModuleNames::contains;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ public abstract class BundleModule {
/** The file of an App Bundle module that contains the APEX manifest. */
public static final ZipPath APEX_MANIFEST_PATH = ZipPath.create("root/apex_manifest.json");

/** The NOTICE file of an APEX Bundle module. */
public static final ZipPath APEX_NOTICE_PATH = ZipPath.create("assets/NOTICE.html.gz");

/** Used to parse file names in the apex/ directory, for multi-Abi targeting. */
public static final Splitter ABI_SPLITTER = Splitter.on(".").omitEmptyStrings();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

package com.android.tools.build.bundletool.model;

import com.google.errorprone.annotations.Immutable;
import com.google.errorprone.annotations.MustBeClosed;
import java.io.InputStream;

/**
* Represents a delegate for a ModuleEntry in a an App Bundle's module.
*
* <p>Useful for selectively overriding certain method(s) while leaving the rest of the
* functionality unchanged.
*/
@Immutable
public class DelegatingModuleEntry implements ModuleEntry {

private final ModuleEntry delegate;

public DelegatingModuleEntry(ModuleEntry delegate) {
this.delegate = delegate;
}

@MustBeClosed
@Override
public InputStream getContent() {
return delegate.getContent();
}

@Override
public ZipPath getPath() {
return delegate.getPath();
}

@Override
public boolean isDirectory() {
return delegate.isDirectory();
}

@Override
public boolean shouldCompress() {
return delegate.shouldCompress();
}

@Override
public ModuleEntry setCompression(boolean shouldCompress) {
return delegate.setCompression(shouldCompress);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -315,15 +315,6 @@ public static Optional<ManifestDeliveryElement> fromManifestElement(
return fromManifestElement(manifestElement, "delivery", isFastFollowAllowed);
}

/**
* Returns the instance of the delivery element for instant delivery if Android Manifest contains
* the <dist:instant-delivery> element.
*/
public static Optional<ManifestDeliveryElement> instantFromManifestElement(
XmlProtoElement manifestElement, boolean isFastFollowAllowed) {
return fromManifestElement(manifestElement, "instant-delivery", isFastFollowAllowed);
}

private static Optional<ManifestDeliveryElement> fromManifestElement(
XmlProtoElement manifestElement, String deliveryTag, boolean isFastFollowAllowed) {
return manifestElement
Expand All @@ -336,6 +327,15 @@ private static Optional<ManifestDeliveryElement> fromManifestElement(
});
}

/**
* Returns the instance of the delivery element for instant delivery if Android Manifest contains
* the <dist:instant-delivery> element.
*/
public static Optional<ManifestDeliveryElement> instantFromManifestElement(
XmlProtoElement manifestElement, boolean isFastFollowAllowed) {
return fromManifestElement(manifestElement, "instant-delivery", isFastFollowAllowed);
}

@VisibleForTesting
static Optional<ManifestDeliveryElement> fromManifestRootNode(
XmlNode xmlNode, boolean isFastFollowAllowed) {
Expand Down
Loading

0 comments on commit 131c1fb

Please sign in to comment.