Skip to content

Commit

Permalink
Prepare for release 1.15.2.
Browse files Browse the repository at this point in the history
  • Loading branch information
MohammadMouadi committed Jul 14, 2023
1 parent f17ce94 commit 4601737
Show file tree
Hide file tree
Showing 41 changed files with 1,208 additions and 274 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ https://developer.android.com/studio/command-line/bundletool

## Releases

Latest release: [1.15.1](https://github.com/google/bundletool/releases)
Latest release: [1.15.2](https://github.com/google/bundletool/releases)
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
release_version = 1.15.1
release_version = 1.15.2
Original file line number Diff line number Diff line change
Expand Up @@ -631,11 +631,10 @@ public BuildApksCommand build() {
.build();
case SYSTEM:
DeviceSpec deviceSpec = command.getDeviceSpec().get();
if (deviceSpec.getScreenDensity() == 0 || deviceSpec.getSupportedAbisList().isEmpty()) {
if (deviceSpec.getSupportedAbisList().isEmpty()) {
throw InvalidCommandException.builder()
.withInternalMessage(
"Device spec must have screen density and ABIs set when running with "
+ "'%s' mode flag. ",
"Device spec must have ABIs set when running with '%s' mode flag.",
SYSTEM.getLowerCaseName())
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static com.android.tools.build.bundletool.commands.BuildApksCommand.ApkBuildMode.SYSTEM;
import static com.android.tools.build.bundletool.commands.ExtractApksCommand.ALL_MODULES_SHORTCUT;
import static com.android.tools.build.bundletool.model.version.VersionGuardedFeature.RESOURCES_REFERENCED_IN_MANIFEST_TO_MASTER_SPLIT;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;

Expand All @@ -43,6 +44,7 @@
import com.android.tools.build.bundletool.model.GeneratedAssetSlices;
import com.android.tools.build.bundletool.model.ModuleDeliveryType;
import com.android.tools.build.bundletool.model.ModuleSplit;
import com.android.tools.build.bundletool.model.OptimizationDimension;
import com.android.tools.build.bundletool.model.exceptions.IncompatibleDeviceException;
import com.android.tools.build.bundletool.model.exceptions.InvalidCommandException;
import com.android.tools.build.bundletool.model.targeting.AlternativeVariantTargetingPopulator;
Expand Down Expand Up @@ -325,7 +327,7 @@ private ApkGenerationConfiguration.Builder getCommonSplitApkGenerationConfigurat
apkGenerationConfiguration.setEnableUncompressedNativeLibraries(
apkOptimizations.getUncompressNativeLibraries());
apkGenerationConfiguration.setEnableDexCompressionSplitter(
apkOptimizations.getUncompressDexFiles());
getEnableUncompressedDexOptimization(appBundle));
apkGenerationConfiguration.setDexCompressionSplitterForTargetSdk(
apkOptimizations.getUncompressedDexTargetSdk());
apkGenerationConfiguration.setEnableSparseEncodingVariant(
Expand Down Expand Up @@ -362,6 +364,20 @@ private ApkGenerationConfiguration.Builder getCommonSplitApkGenerationConfigurat
return apkGenerationConfiguration;
}

private boolean getEnableUncompressedDexOptimization(AppBundle appBundle) {
if (appBundle.getUncompressedDexOptOut()) {
return false;
}
if (appBundle.getBundleConfig().getOptimizations().hasUncompressDexFiles()) {
// If uncompressed dex is specified in the BundleConfig it will be honoured.
return appBundle.getBundleConfig().getOptimizations().getUncompressDexFiles().getEnabled();
}
// This is the default value of the optimisation. Depends on the bundletool version.
boolean enableUncompressedDexOptimization = apkOptimizations.getUncompressDexFiles();

return enableUncompressedDexOptimization;
}

private ApkGenerationConfiguration getAssetSliceGenerationConfiguration() {
return ApkGenerationConfiguration.builder()
.setEnableBaseModuleMinSdkAsDefaultTargeting(
Expand Down Expand Up @@ -397,7 +413,18 @@ private boolean matchModuleToDevice(BundleModule module) {

private ApkOptimizations getSystemApkOptimizations() {
ImmutableSet<SystemApkOption> systemApkOptions = command.getSystemApkOptions();
return apkOptimizations.toBuilder()
ApkOptimizations.Builder apkOptimizationsBuilder = apkOptimizations.toBuilder();

checkArgument(deviceSpec.isPresent(), "Must specify a device spec in system mode");
if (deviceSpec.get().getScreenDensity() == 0) {
// If no screen density is specified, then don't split by screen density.
apkOptimizationsBuilder.setSplitDimensions(
Sets.difference(
apkOptimizations.getSplitDimensions(),
ImmutableSet.of(OptimizationDimension.SCREEN_DENSITY))
.immutableCopy());
}
return apkOptimizationsBuilder
.setUncompressNativeLibraries(
systemApkOptions.contains(SystemApkOption.UNCOMPRESSED_NATIVE_LIBRARIES))
.setUncompressDexFiles(systemApkOptions.contains(SystemApkOption.UNCOMPRESSED_DEX_FILES))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,21 @@

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

import static com.android.tools.build.bundletool.commands.BuildApksCommand.OutputFormat.APK_SET;
import static com.android.tools.build.bundletool.commands.BuildApksCommand.OutputFormat.DIRECTORY;
import static com.android.tools.build.bundletool.model.utils.BundleParser.EXTRACTED_SDK_MODULES_FILE_NAME;
import static com.android.tools.build.bundletool.model.utils.BundleParser.getModulesZip;
import static com.android.tools.build.bundletool.model.utils.files.FilePreconditions.checkFileDoesNotExist;
import static com.android.tools.build.bundletool.model.utils.files.FilePreconditions.checkFileExistsAndReadable;
import static com.android.tools.build.bundletool.model.utils.files.FilePreconditions.checkFileHasExtension;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.joining;

import com.android.bundle.RuntimeEnabledSdkConfigProto.SdkSplitPropertiesInheritedFromApp;
import com.android.tools.build.bundletool.androidtools.Aapt2Command;
import com.android.tools.build.bundletool.commands.BuildApksCommand.OutputFormat;
import com.android.tools.build.bundletool.commands.CommandHelp.CommandDescription;
import com.android.tools.build.bundletool.commands.CommandHelp.FlagDescription;
import com.android.tools.build.bundletool.flags.Flag;
Expand All @@ -41,10 +47,12 @@
import com.android.tools.build.bundletool.model.utils.DefaultSystemEnvironmentProvider;
import com.android.tools.build.bundletool.model.utils.SystemEnvironmentProvider;
import com.android.tools.build.bundletool.model.utils.files.BufferedIo;
import com.android.tools.build.bundletool.model.utils.files.FileUtils;
import com.android.tools.build.bundletool.sdkmodule.SdkModuleToAppBundleModuleConverter;
import com.android.tools.build.bundletool.validation.SdkAsarValidator;
import com.android.tools.build.bundletool.validation.SdkBundleValidator;
import com.google.auto.value.AutoValue;
import com.google.common.io.MoreFiles;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
Expand All @@ -53,9 +61,12 @@
import java.io.PrintStream;
import java.io.Reader;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

Expand All @@ -65,8 +76,12 @@ public abstract class BuildSdkApksForAppCommand {

private static final int DEFAULT_THREAD_POOL_SIZE = 4;

private static final String APK_SET_ARCHIVE_EXTENSION = "apks";

public static final String COMMAND_NAME = "build-sdk-apks-for-app";

private static final Logger logger = Logger.getLogger(BuildSdkApksForAppCommand.class.getName());

private static final Flag<Path> SDK_BUNDLE_LOCATION_FLAG = Flag.path("sdk-bundle");

private static final Flag<Path> SDK_ARCHIVE_LOCATION_FLAG = Flag.path("sdk-archive");
Expand All @@ -76,6 +91,9 @@ public abstract class BuildSdkApksForAppCommand {

private static final Flag<Path> OUTPUT_FILE_FLAG = Flag.path("output");

private static final Flag<OutputFormat> OUTPUT_FORMAT_FLAG =
Flag.enumFlag("output-format", OutputFormat.class);

private static final Flag<Path> AAPT2_PATH_FLAG = Flag.path("aapt2");

// Signing-related flags: should match flags from apksig library.
Expand All @@ -95,6 +113,8 @@ public abstract class BuildSdkApksForAppCommand {

public abstract Path getOutputFile();

public abstract OutputFormat getOutputFormat();

public abstract Optional<Aapt2Command> getAapt2Command();

public abstract Optional<SigningConfiguration> getSigningConfiguration();
Expand All @@ -108,7 +128,7 @@ ListeningExecutorService getExecutorService() {
abstract boolean isExecutorServiceCreatedByBundleTool();

public static BuildSdkApksForAppCommand.Builder builder() {
return new AutoValue_BuildSdkApksForAppCommand.Builder();
return new AutoValue_BuildSdkApksForAppCommand.Builder().setOutputFormat(APK_SET);
}

/** Builder for {@link BuildSdkApksForAppCommand}. */
Expand All @@ -122,7 +142,7 @@ public abstract static class Builder {
public abstract Builder setSdkArchivePath(Path sdkArchivePath);

/** Sets the config containing app properties that the SDK split should inherit. */
abstract Builder setInheritedAppProperties(
public abstract Builder setInheritedAppProperties(
SdkSplitPropertiesInheritedFromApp sdkSplitPropertiesInheritedFromApp);

/** Sets path to a config file containing app properties that the SDK split should inherit. */
Expand All @@ -133,6 +153,9 @@ public Builder setInheritedAppProperties(Path inheritedAppProperties) {
/** Path to the output produced by this command. Must have extension ".apks". */
public abstract Builder setOutputFile(Path outputFile);

/** Sets the output format. */
public abstract Builder setOutputFormat(OutputFormat outputFormat);

/** Provides a wrapper around the execution of the aapt2 command. */
public abstract Builder setAapt2Command(Aapt2Command aapt2Command);

Expand Down Expand Up @@ -211,7 +234,22 @@ public static CommandHelp help() {
FlagDescription.builder()
.setFlagName(OUTPUT_FILE_FLAG.getName())
.setExampleValue("output.apks")
.setDescription("Path to where the APK Set archive should be created.")
.setDescription(
"Path to where the APK Set archive should be created (default) or path to the"
+ " directory where generated APKs should be stored when flag --%s is set"
+ " to '%s'.",
OUTPUT_FORMAT_FLAG.getName(), DIRECTORY)
.build())
.addFlag(
FlagDescription.builder()
.setFlagName(OUTPUT_FORMAT_FLAG.getName())
.setExampleValue(joinFlagOptions(OutputFormat.values()))
.setOptional(true)
.setDescription(
"Specifies output format for generated APKs. If set to '%s' outputs APKs into"
+ " the created APK Set archive (default). If set to '%s' outputs APKs"
+ " into the specified directory.",
APK_SET, DIRECTORY)
.build())
.addFlag(
FlagDescription.builder()
Expand Down Expand Up @@ -267,6 +305,10 @@ public static CommandHelp help() {
.build();
}

private static String joinFlagOptions(Enum<?>... flagOptions) {
return stream(flagOptions).map(Enum::name).map(String::toLowerCase).collect(joining("|"));
}

public static BuildSdkApksForAppCommand fromFlags(ParsedFlags flags) {
return fromFlags(flags, System.out, DEFAULT_PROVIDER);
}
Expand All @@ -278,6 +320,7 @@ static BuildSdkApksForAppCommand fromFlags(
.setInheritedAppProperties(
INHERITED_APP_PROPERTIES_LOCATION_FLAG.getRequiredValue(flags))
.setOutputFile(OUTPUT_FILE_FLAG.getRequiredValue(flags));
OUTPUT_FORMAT_FLAG.getValue(flags).ifPresent(command::setOutputFormat);
SDK_BUNDLE_LOCATION_FLAG.getValue(flags).ifPresent(command::setSdkBundlePath);
SDK_ARCHIVE_LOCATION_FLAG.getValue(flags).ifPresent(command::setSdkArchivePath);
AAPT2_PATH_FLAG
Expand All @@ -290,15 +333,26 @@ static BuildSdkApksForAppCommand fromFlags(
return command.build();
}

public void execute() {
@CanIgnoreReturnValue
public Path execute() {
validateInput();

Path outputDirectory =
getOutputFormat().equals(APK_SET) ? getOutputFile().getParent() : getOutputFile();
if (outputDirectory != null && Files.notExists(outputDirectory)) {
logger.info("Output directory '" + outputDirectory + "' does not exist, creating it.");
FileUtils.createDirectories(outputDirectory);
}

if (getSdkBundlePath().isPresent()) {
executeForSdkBundle();
} else if (getSdkArchivePath().isPresent()) {
executeForSdkArchive();
} else {
throw new IllegalStateException("whaaat");
throw new IllegalStateException(
"One and only one of SdkBundlePath and SdkArchivePath should be set.");
}
return getOutputFile();
}

private void validateInput() {
Expand All @@ -310,6 +364,16 @@ private void validateInput() {
checkFileExistsAndReadable(getSdkArchivePath().get());
checkFileHasExtension("ASAR file", getSdkArchivePath().get(), ".asar");
}
if (getOutputFormat().equals(APK_SET)) {
if (!Objects.equals(MoreFiles.getFileExtension(getOutputFile()), APK_SET_ARCHIVE_EXTENSION)) {
throw InvalidCommandException.builder()
.withInternalMessage(
"Flag --output should be the path where to generate the APK Set. "
+ "Its extension must be '.apks'.")
.build();
}
checkFileDoesNotExist(getOutputFile());
}
}

private void executeForSdkBundle() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
import com.android.tools.build.bundletool.model.GeneratedApks;
import com.android.tools.build.bundletool.model.GeneratedAssetSlices;
import com.android.tools.build.bundletool.model.ModuleSplit;
import com.android.tools.build.bundletool.model.exceptions.InvalidCommandException;
import com.android.tools.build.bundletool.shards.ModuleSplitterForShards;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.nio.file.Path;
import java.util.Optional;
import javax.inject.Inject;

Expand Down Expand Up @@ -59,14 +61,25 @@ void execute() {
moduleSplitterForShards.generateSplits(module, /* shardingDimensions= */ ImmutableSet.of());

GeneratedApks generatedApks = GeneratedApks.fromModuleSplits(splits);
ApkSetWriter apkSetWriter = ApkSetWriter.zip(tempDirectory.getPath(), command.getOutputFile());

apkSerializerManager.serializeApkSetWithoutToc(
apkSetWriter,
createApkSetWriter(tempDirectory.getPath()),
generatedApks,
GeneratedAssetSlices.builder().build(),
/* deviceSpec= */ Optional.empty(),
LocalTestingInfo.getDefaultInstance(),
/* permanentlyFusedModules= */ ImmutableSet.of());
}

private ApkSetWriter createApkSetWriter(Path tempDir) {
switch (command.getOutputFormat()) {
case APK_SET:
return ApkSetWriter.zip(tempDir, command.getOutputFile());
case DIRECTORY:
return ApkSetWriter.directory(command.getOutputFile());
}
throw InvalidCommandException.builder()
.withInternalMessage("Unsupported output format '%s'.", command.getOutputFormat())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,11 @@ private void validateInput() {
!getOutputDirectory().isPresent(),
"Output directory should not be set when APKs are inside directory.");
checkDirectoryExists(getApksArchivePath());
checkFileExistsAndReadable(getApksArchivePath().resolve(FileNames.TABLE_OF_CONTENTS_FILE));
Path tocFile =
Files.exists(getApksArchivePath().resolve(FileNames.TABLE_OF_CONTENTS_JSON_FILE))
? getApksArchivePath().resolve(FileNames.TABLE_OF_CONTENTS_JSON_FILE)
: getApksArchivePath().resolve(FileNames.TABLE_OF_CONTENTS_FILE);
checkFileExistsAndReadable(tocFile);
} else {
checkFileExistsAndReadable(getApksArchivePath());
}
Expand Down
Loading

0 comments on commit 4601737

Please sign in to comment.