Skip to content

Commit

Permalink
Prepare for release 0.13.0.
Browse files Browse the repository at this point in the history
  • Loading branch information
plecesne committed Feb 6, 2020
1 parent 3586f86 commit 6a80c81
Show file tree
Hide file tree
Showing 54 changed files with 1,885 additions and 424 deletions.
Empty file modified .github/ISSUE_TEMPLATE/Bug_report.md
100644 → 100755
Empty file.
Empty file modified .github/ISSUE_TEMPLATE/Custom.md
100644 → 100755
Empty file.
Empty file modified .github/ISSUE_TEMPLATE/Feature_request.md
100644 → 100755
Empty file.
Empty file modified .gitignore
100644 → 100755
Empty file.
Empty file modified CONTRIBUTING.md
100644 → 100755
Empty file.
Empty file modified LICENSE
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion README.md
100644 → 100755
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.12.0](https://github.com/google/bundletool/releases)
Latest release: [0.13.0](https://github.com/google/bundletool/releases)
Empty file modified build.gradle
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion gradle.properties
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1 +1 @@
release_version = 0.12.0
release_version = 0.13.0
Empty file modified gradle/wrapper/gradle-wrapper.jar
100644 → 100755
Empty file.
Empty file modified gradle/wrapper/gradle-wrapper.properties
100644 → 100755
Empty file.
Empty file modified gradlew.bat
100644 → 100755
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.android.tools.build.bundletool.model.OptimizationDimension;
import com.android.tools.build.bundletool.model.Password;
import com.android.tools.build.bundletool.model.SigningConfiguration;
import com.android.tools.build.bundletool.model.SourceStamp;
import com.android.tools.build.bundletool.model.exceptions.CommandExecutionException;
import com.android.tools.build.bundletool.model.exceptions.ValidationException;
import com.android.tools.build.bundletool.model.utils.DefaultSystemEnvironmentProvider;
Expand Down Expand Up @@ -105,7 +106,9 @@ public final boolean isAnySystemMode() {
Flag.enumSet("optimize-for", OptimizationDimension.class);
private static final Flag<Path> AAPT2_PATH_FLAG = Flag.path("aapt2");
private static final Flag<Integer> MAX_THREADS_FLAG = Flag.positiveInteger("max-threads");
private static final Flag<ApkBuildMode> MODE_FLAG = Flag.enumFlag("mode", ApkBuildMode.class);
private static final Flag<ApkBuildMode> BUILD_MODE_FLAG =
Flag.enumFlag("mode", ApkBuildMode.class);
private static final Flag<Boolean> LOCAL_TESTING_MODE_FLAG = Flag.booleanFlag("local-testing");

private static final Flag<Path> ADB_PATH_FLAG = Flag.path("adb");
private static final Flag<Boolean> CONNECTED_DEVICE_FLAG = Flag.booleanFlag("connected-device");
Expand All @@ -118,8 +121,9 @@ public final boolean isAnySystemMode() {
// Signing-related flags: should match flags from apksig library.
private static final Flag<Path> KEYSTORE_FLAG = Flag.path("ks");
private static final Flag<String> KEY_ALIAS_FLAG = Flag.string("ks-key-alias");
private static final Flag<Password> KEYSTORE_PASSWORD = Flag.password("ks-pass");
private static final Flag<Password> KEY_PASSWORD = Flag.password("key-pass");
private static final Flag<Password> KEYSTORE_PASSWORD_FLAG = Flag.password("ks-pass");
private static final Flag<Password> KEY_PASSWORD_FLAG = Flag.password("key-pass");


private static final String APK_SET_ARCHIVE_EXTENSION = "apks";

Expand Down Expand Up @@ -150,6 +154,8 @@ public final boolean isAnySystemMode() {

public abstract ApkBuildMode getApkBuildMode();

public abstract boolean getLocalTestingMode();

public abstract Optional<Aapt2Command> getAapt2Command();

public abstract Optional<SigningConfiguration> getSigningConfiguration();
Expand All @@ -175,10 +181,12 @@ ListeningExecutorService getExecutorService() {

public abstract Optional<PrintStream> getOutputPrintStream();


public static Builder builder() {
return new AutoValue_BuildApksCommand.Builder()
.setOverwriteOutput(false)
.setApkBuildMode(DEFAULT)
.setLocalTestingMode(false)
.setGenerateOnlyForConnectedDevice(false)
.setCreateApkSetArchive(true)
.setOptimizationDimensions(ImmutableSet.of())
Expand Down Expand Up @@ -215,6 +223,13 @@ public abstract Builder setOptimizationDimensions(
*/
public abstract Builder setApkBuildMode(ApkBuildMode mode);

/**
* Sets whether the APKs should be built in local testing mode.
*
* <p>The default is {@code false}.
*/
public abstract Builder setLocalTestingMode(boolean enableLocalTesting);

/**
* Sets if the generated APK Set will contain APKs compatible only with the connected device.
*/
Expand Down Expand Up @@ -316,6 +331,7 @@ public Builder setExecutorService(ListeningExecutorService executorService) {
/** For command line, sets the {@link PrintStream} to use for outputting the warnings. */
public abstract Builder setOutputPrintStream(PrintStream outputPrintStream);


abstract BuildApksCommand autoBuild();

public BuildApksCommand build() {
Expand Down Expand Up @@ -436,7 +452,8 @@ static BuildApksCommand fromFlags(
aapt2Path ->
buildApksCommand.setAapt2Command(Aapt2Command.createFromExecutablePath(aapt2Path)));

MODE_FLAG.getValue(flags).ifPresent(buildApksCommand::setApkBuildMode);
BUILD_MODE_FLAG.getValue(flags).ifPresent(buildApksCommand::setApkBuildMode);
LOCAL_TESTING_MODE_FLAG.getValue(flags).ifPresent(buildApksCommand::setLocalTestingMode);
MAX_THREADS_FLAG
.getValue(flags)
.ifPresent(
Expand All @@ -449,8 +466,8 @@ static BuildApksCommand fromFlags(
// Signing-related arguments.
Optional<Path> keystorePath = KEYSTORE_FLAG.getValue(flags);
Optional<String> keyAlias = KEY_ALIAS_FLAG.getValue(flags);
Optional<Password> keystorePassword = KEYSTORE_PASSWORD.getValue(flags);
Optional<Password> keyPassword = KEY_PASSWORD.getValue(flags);
Optional<Password> keystorePassword = KEYSTORE_PASSWORD_FLAG.getValue(flags);
Optional<Password> keyPassword = KEY_PASSWORD_FLAG.getValue(flags);

if (keystorePath.isPresent() && keyAlias.isPresent()) {
buildApksCommand.setSigningConfiguration(
Expand Down Expand Up @@ -505,7 +522,7 @@ static BuildApksCommand fromFlags(
buildApksCommand.setAdbPath(adbPath).setAdbServer(adbServer);
}

ApkBuildMode apkBuildMode = MODE_FLAG.getValue(flags).orElse(DEFAULT);
ApkBuildMode apkBuildMode = BUILD_MODE_FLAG.getValue(flags).orElse(DEFAULT);
boolean supportsPartialDeviceSpecs = apkBuildMode.isAnySystemMode();

Function<Path, DeviceSpec> deviceSpecParser =
Expand Down Expand Up @@ -592,7 +609,7 @@ public static CommandHelp help() {
.build())
.addFlag(
FlagDescription.builder()
.setFlagName(MODE_FLAG.getName())
.setFlagName(BUILD_MODE_FLAG.getName())
.setExampleValue(joinFlagOptions(ApkBuildMode.values()))
.setOptional(true)
.setDescription(
Expand Down Expand Up @@ -628,7 +645,7 @@ public static CommandHelp help() {
+ "Acceptable values are '%s'. This flag should be only be set with "
+ "--%s=%s flag.",
joinFlagOptions(OptimizationDimension.values()),
MODE_FLAG.getName(),
BUILD_MODE_FLAG.getName(),
DEFAULT.getLowerCaseName())
.build())
.addFlag(
Expand All @@ -652,7 +669,7 @@ public static CommandHelp help() {
.build())
.addFlag(
FlagDescription.builder()
.setFlagName(KEYSTORE_PASSWORD.getName())
.setFlagName(KEYSTORE_PASSWORD_FLAG.getName())
.setExampleValue("[pass|file]:value")
.setOptional(true)
.setDescription(
Expand All @@ -664,7 +681,7 @@ public static CommandHelp help() {
.build())
.addFlag(
FlagDescription.builder()
.setFlagName(KEY_PASSWORD.getName())
.setFlagName(KEY_PASSWORD_FLAG.getName())
.setExampleValue("key-password")
.setOptional(true)
.setDescription(
Expand All @@ -683,7 +700,7 @@ public static CommandHelp help() {
"If set, will generate APK Set optimized for the connected device. The "
+ "generated APK Set will only be installable on that specific class of "
+ "devices. This flag should be only be set with --%s=%s flag.",
MODE_FLAG.getName(), DEFAULT.getLowerCaseName())
BUILD_MODE_FLAG.getName(), DEFAULT.getLowerCaseName())
.build())
.addFlag(
FlagDescription.builder()
Expand Down Expand Up @@ -716,7 +733,7 @@ public static CommandHelp help() {
+ "it will generate an APK Set optimized for the specified device spec. "
+ "This flag should be only be set with --%s=%s flag.",
GetDeviceSpecCommand.COMMAND_NAME,
MODE_FLAG.getName(),
BUILD_MODE_FLAG.getName(),
DEFAULT.getLowerCaseName())
.build())
.addFlag(
Expand All @@ -731,6 +748,18 @@ public static CommandHelp help() {
SYSTEM.getLowerCaseName(),
SYSTEM_COMPRESSED.getLowerCaseName())
.build())
.addFlag(
FlagDescription.builder()
.setFlagName(LOCAL_TESTING_MODE_FLAG.getName())
.setOptional(true)
.setDescription(
"If enabled, the APK set will be built in local testing mode, which includes"
+ " additional metadata in the output. When `bundletool %s` is later used"
+ " to install APKs from this set on a device, it will additionally push"
+ " all dynamic module splits and asset packs to a location that can be"
+ " accessed by the Play Core API.",
InstallApksCommand.COMMAND_NAME)
.build())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;

import com.android.bundle.Commands.LocalTestingInfo;
import com.android.bundle.Config.BundleConfig;
import com.android.bundle.Config.Compression;
import com.android.bundle.Config.SuffixStripping;
Expand Down Expand Up @@ -62,6 +63,8 @@
import com.android.tools.build.bundletool.optimizations.ApkOptimizations;
import com.android.tools.build.bundletool.optimizations.OptimizationsMerger;
import com.android.tools.build.bundletool.preprocessors.AppBundle64BitNativeLibrariesPreprocessor;
import com.android.tools.build.bundletool.preprocessors.EntryCompressionPreprocessor;
import com.android.tools.build.bundletool.preprocessors.LocalTestingPreprocessor;
import com.android.tools.build.bundletool.splitters.ApkGenerationConfiguration;
import com.android.tools.build.bundletool.splitters.AssetSlicesGenerator;
import com.android.tools.build.bundletool.splitters.ResourceAnalyzer;
Expand All @@ -79,6 +82,7 @@
import java.util.logging.Logger;
import java.util.stream.Stream;
import java.util.zip.ZipFile;
import javax.annotation.CheckReturnValue;

/** Executes the "build-apks" command. */
final class BuildApksManager {
Expand Down Expand Up @@ -137,9 +141,7 @@ private void executeWithZip(ZipFile bundleZip, Optional<DeviceSpec> deviceSpec)
AppBundle appBundle = AppBundle.buildFromZip(bundleZip);
bundleValidator.validate(appBundle);

appBundle =
new AppBundle64BitNativeLibrariesPreprocessor(command.getOutputPrintStream())
.preprocess(appBundle);
appBundle = applyPreprocessors(appBundle);

ImmutableSet<BundleModule> requestedModules =
command.getModules().isEmpty()
Expand Down Expand Up @@ -230,8 +232,13 @@ private void executeWithZip(ZipFile bundleZip, Optional<DeviceSpec> deviceSpec)
command.getApkListener().orElse(ApkListener.NO_OP),
command.getApkModifier().orElse(ApkModifier.NO_OP),
command.getFirstVariantNumber().orElse(0));

apkSerializerManager.populateApkSetBuilder(
generatedApks, generatedAssetSlices.build(), command.getApkBuildMode(), deviceSpec);
generatedApks,
generatedAssetSlices.build(),
command.getApkBuildMode(),
deviceSpec,
getLocalTestingInfo(appBundle));

if (command.getOverwriteOutput()) {
Files.deleteIfExists(command.getOutputFile());
Expand Down Expand Up @@ -382,7 +389,10 @@ private ApkGenerationConfiguration.Builder getCommonSplitApkGenerationConfigurat
installLocation.equals("auto") || installLocation.equals("preferExternal"))
.orElse(false));

apkGenerationConfiguration.setMasterPinnedResources(appBundle.getMasterPinnedResources());
apkGenerationConfiguration.setMasterPinnedResourceIds(appBundle.getMasterPinnedResourceIds());

apkGenerationConfiguration.setMasterPinnedResourceNames(
appBundle.getMasterPinnedResourceNames());

apkGenerationConfiguration.setSuffixStrippings(getSuffixStrippings(bundleConfig));

Expand Down Expand Up @@ -471,6 +481,30 @@ private static boolean shouldStrip64BitLibrariesFromShards(AppBundle appBundle)
.getStrip64BitLibraries();
}

@CheckReturnValue
private AppBundle applyPreprocessors(AppBundle bundle) {
bundle =
new AppBundle64BitNativeLibrariesPreprocessor(command.getOutputPrintStream())
.preprocess(bundle);
if (command.getLocalTestingMode()) {
bundle = new LocalTestingPreprocessor().preprocess(bundle);
}
bundle = new EntryCompressionPreprocessor().preprocess(bundle);
return bundle;
}

private static LocalTestingInfo getLocalTestingInfo(AppBundle bundle) {
LocalTestingInfo.Builder localTestingInfo = LocalTestingInfo.newBuilder();
bundle
.getBaseModule()
.getAndroidManifest()
.getMetadataValue(LocalTestingPreprocessor.METADATA_NAME)
.ifPresent(
localTestingPath ->
localTestingInfo.setEnabled(true).setLocalTestingPath(localTestingPath));
return localTestingInfo.build();
}

private static class ApksToGenerate {
private final AppBundle appBundle;
private final ApkBuildMode apkBuildMode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
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 @@ -169,26 +168,7 @@ ImmutableList<Path> execute(PrintStream output) {

BuildApksResult toc = ResultUtils.readTableOfContents(getApksArchivePath());
Optional<ImmutableSet<String>> requestedModuleNames =
getModules()
.map(
modules ->
modules.contains(ALL_MODULES_SHORTCUT)
? 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);
getModules().map(modules -> resolveRequestedModules(modules, toc));

ApkMatcher apkMatcher = new ApkMatcher(getDeviceSpec(), requestedModuleNames, getInstant());
ImmutableList<ZipPath> matchedApks = apkMatcher.getMatchingApks(toc);
Expand All @@ -207,6 +187,20 @@ ImmutableList<Path> execute(PrintStream output) {
}
}

static ImmutableSet<String> resolveRequestedModules(
ImmutableSet<String> requestedModules, BuildApksResult toc) {
return requestedModules.contains(ALL_MODULES_SHORTCUT)
? Stream.concat(
toc.getVariantList().stream()
.flatMap(variant -> variant.getApkSetList().stream())
.map(apkSet -> apkSet.getModuleMetadata().getName()),
toc.getAssetSliceSetList().stream()
.map(AssetSliceSet::getAssetModuleMetadata)
.map(AssetModuleMetadata::getName))
.collect(toImmutableSet())
: requestedModules;
}

private void validateInput() {
if (getModules().isPresent() && getModules().get().isEmpty()) {
throw new ValidationException("The set of modules cannot be empty.");
Expand All @@ -223,33 +217,6 @@ 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
Loading

0 comments on commit 6a80c81

Please sign in to comment.