Skip to content

Commit

Permalink
Prepare for release 1.8.1.
Browse files Browse the repository at this point in the history
  • Loading branch information
Iurii Makhno committed Sep 30, 2021
1 parent e6f6a86 commit 5ba6c05
Show file tree
Hide file tree
Showing 26 changed files with 606 additions and 94 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ https://developer.android.com/studio/command-line/bundletool

## Releases

Latest release: [1.8.0](https://github.com/google/bundletool/releases)
Latest release: [1.8.1](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.8.0
release_version = 1.8.1
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ public enum OutputFormat {
private static final Flag<String> KEY_ALIAS_FLAG = Flag.string("ks-key-alias");
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 Flag<Integer> MINIMUM_V3_SIGNING_API_VERSION_FLAG =
Flag.positiveInteger("min-v3-signing-api-version");
private static final Flag<Integer> MINIMUM_V3_ROTATION_API_VERSION_FLAG =
Flag.positiveInteger("min-v3-rotation-api-version");

// SourceStamp-related flags.
private static final Flag<Boolean> CREATE_STAMP_FLAG = Flag.booleanFlag("create-stamp");
Expand Down Expand Up @@ -891,12 +891,12 @@ public static CommandHelp help() {
.build())
.addFlag(
FlagDescription.builder()
.setFlagName(MINIMUM_V3_SIGNING_API_VERSION_FLAG.getName())
.setFlagName(MINIMUM_V3_ROTATION_API_VERSION_FLAG.getName())
.setExampleValue("30")
.setOptional(true)
.setDescription(
"The minimum API version for signing the generated APKs using V3 signature"
+ " scheme.")
"The minimum API version for signing the generated APKs with rotation using V3"
+ " signature scheme.")
.build())
.addFlag(
FlagDescription.builder()
Expand Down Expand Up @@ -1120,7 +1120,7 @@ private static void populateSigningConfigurationFromFlags(
Optional<String> keyAlias = KEY_ALIAS_FLAG.getValue(flags);
Optional<Password> keystorePassword = KEYSTORE_PASSWORD_FLAG.getValue(flags);
Optional<Password> keyPassword = KEY_PASSWORD_FLAG.getValue(flags);
Optional<Integer> minV3SigningApi = MINIMUM_V3_SIGNING_API_VERSION_FLAG.getValue(flags);
Optional<Integer> minV3RotationApi = MINIMUM_V3_ROTATION_API_VERSION_FLAG.getValue(flags);

if (keystorePath.isPresent() && keyAlias.isPresent()) {
SignerConfig signerConfig =
Expand All @@ -1129,7 +1129,7 @@ private static void populateSigningConfigurationFromFlags(
SigningConfiguration.Builder builder =
SigningConfiguration.builder()
.setSignerConfig(signerConfig)
.setMinimumV3RotationApiVersion(minV3SigningApi);
.setMinimumV3RotationApiVersion(minV3RotationApi);
populateLineageFromFlags(builder, flags);
buildApksCommand.setSigningConfiguration(builder.build());
} else if (keystorePath.isPresent() && !keyAlias.isPresent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.android.tools.build.bundletool.device.Device;
import com.android.tools.build.bundletool.device.Device.InstallOptions;
import com.android.tools.build.bundletool.device.DeviceAnalyzer;
import com.android.tools.build.bundletool.device.LocalTestingPathResolver;
import com.android.tools.build.bundletool.flags.Flag;
import com.android.tools.build.bundletool.flags.ParsedFlags;
import com.android.tools.build.bundletool.io.TempDirectory;
Expand All @@ -50,6 +51,7 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.protobuf.Int32Value;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
Expand Down Expand Up @@ -215,9 +217,30 @@ public void execute() {
if (!filesToPush.isEmpty()) {
pushFiles(filesToPush, toc, adbRunner);
}
if (toc.getLocalTestingInfo().getEnabled()) {
cleanUpEmulatedSplits(adbRunner, toc);
}
}
}

private void cleanUpEmulatedSplits(AdbRunner adbRunner, BuildApksResult toc) {
adbRunner.run(
device -> {
try {
device.removeRemotePath(
LocalTestingPathResolver.getLocalTestingWorkingDir(toc.getPackageName()),
Optional.of(toc.getPackageName()),
getTimeout());
} catch (IOException e) {
System.err.println(
"Failed to remove working directory with local testing splits. Your app might"
+ " still have been installed correctly but have previous version of"
+ " dynamic feature modules. If you see legacy versions of dynamic feature"
+ " modules installed try to uninstall and install the app again.");
}
});
}

/** Extracts the apks that will be installed. */
private ImmutableList<Path> getApksToInstall(
BuildApksResult toc, DeviceSpec deviceSpec, Path output) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
import static com.android.tools.build.bundletool.device.LocalTestingPathResolver.resolveLocalTestingPath;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.util.Arrays.stream;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES;

import com.android.ddmlib.AdbCommandRejectedException;
import com.android.ddmlib.DdmPreferences;
Expand All @@ -34,19 +37,21 @@
import com.android.tools.build.bundletool.model.exceptions.CommandExecutionException;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.primitives.Ints;
import com.google.errorprone.annotations.FormatMethod;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Clock;
import java.util.Arrays;
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/** Ddmlib-backed implementation of the {@link Device}. */
public class DdmlibDevice extends Device {
private static final String DENSITY_OUTPUT_PREFIX = "Physical density:";

private final IDevice device;
private final Clock clock;
Expand Down Expand Up @@ -84,7 +89,40 @@ public ImmutableList<String> getAbis() {

@Override
public int getDensity() {
return device.getDensity();
int density = device.getDensity();
if (density != -1) {
return density;
}
// This might be a case when ddmlib is unable to retrieve density via reading properties.
// For example this happens on Android S emulator.
try {
int[] parsedDensityFromShell = new int[] {-1};
device.executeShellCommand(
"wm density",
new MultiLineReceiver() {
@Override
public void processNewLines(String[] lines) {
stream(lines)
.filter(string -> string.startsWith(DENSITY_OUTPUT_PREFIX))
.map(string -> string.substring(DENSITY_OUTPUT_PREFIX.length()).trim())
.map(Ints::tryParse)
.forEach(density -> parsedDensityFromShell[0] = density != null ? density : -1);
}

@Override
public boolean isCancelled() {
return false;
}
},
/* maxTimeToOutputResponse= */ 1,
MINUTES);
return parsedDensityFromShell[0];
} catch (TimeoutException
| AdbCommandRejectedException
| ShellCommandUnresponsiveException
| IOException e) {
return -1;
}
}

@Override
Expand All @@ -101,14 +139,13 @@ public Optional<String> getProperty(String propertyName) {
public ImmutableList<String> getDeviceFeatures() {
return deviceFeaturesParser.parse(
new AdbShellCommandTask(this, DEVICE_FEATURES_COMMAND)
.execute(ADB_TIMEOUT_MS, TimeUnit.MILLISECONDS));
.execute(ADB_TIMEOUT_MS, MILLISECONDS));
}

@Override
public ImmutableList<String> getGlExtensions() {
return glExtensionsParser.parse(
new AdbShellCommandTask(this, GL_EXTENSIONS_COMMAND)
.execute(ADB_TIMEOUT_MS, TimeUnit.MILLISECONDS));
new AdbShellCommandTask(this, GL_EXTENSIONS_COMMAND).execute(ADB_TIMEOUT_MS, MILLISECONDS));
}

@Override
Expand Down Expand Up @@ -141,7 +178,7 @@ public void installApks(ImmutableList<Path> apks, InstallOptions installOptions)
installOptions.getAllowReinstall(),
extraArgs.build(),
installOptions.getTimeout().toMillis(),
TimeUnit.MILLISECONDS);
MILLISECONDS);
} else {
device.installPackage(
Iterables.getOnlyElement(apkFiles).toString(),
Expand Down Expand Up @@ -177,10 +214,14 @@ public void push(ImmutableList<Path> files, PushOptions pushOptions) {
// ... and recreate it, making sure the destination dir is empty.
// We don't want splits from previous runs in the directory.
// There isn't a nice way to test if dir is empty in shell, but rmdir will return error
commandExecutor.executeAndPrint(
"mkdir -p %s && rmdir %s && mkdir -p %s", splitsPath, splitsPath, splitsPath);
commandExecutor.executeAndPrint("mkdir -p %s && rmdir %1$s && mkdir -p %1$s", splitsPath);

pushFiles(commandExecutor, splitsPath, files);

// Fix permission issue for devices on Android S.
if (device.getVersion().getApiLevel() >= 31 || device.getVersion().isPreview()) {
commandExecutor.executeAndPrint("chmod 775 %s", splitsPath);
}
} catch (IOException
| TimeoutException
| SyncException
Expand Down Expand Up @@ -233,8 +274,23 @@ public Path syncPackageToDevice(Path localFilePath)
}

@Override
public void removeRemotePackage(Path remoteFilePath) throws InstallException {
device.removeRemotePackage(remoteFilePath.toString());
public void removeRemotePath(
String remoteFilePath, Optional<String> runAsPackageName, Duration timeout)
throws IOException {
RemoteCommandExecutor executor =
new RemoteCommandExecutor(this, timeout.toMillis(), System.err);
try {
if (runAsPackageName.isPresent()) {
executor.executeAndPrint("run-as %s rm -rf %s", runAsPackageName.get(), remoteFilePath);
} else {
executor.executeAndPrint("rm -rf %s", remoteFilePath);
}
} catch (TimeoutException
| AdbCommandRejectedException
| ShellCommandUnresponsiveException
| IOException e) {
throw new IOException(String.format("Failed to remove '%s'", remoteFilePath), e);
}
}

@Override
Expand Down Expand Up @@ -291,7 +347,7 @@ private void executeAndPrint(String commandFormat, String... args)
// ExecuteShellCommand would only tell us about ADB errors, and NOT the actual shell commands
// We need another way to check exit values of the commands we run.
// By adding " && echo OK" we can make sure "OK" is printed if the cmd executed successfully.
device.executeShellCommand(command + " && echo OK", receiver, timeout, TimeUnit.MILLISECONDS);
device.executeShellCommand(command + " && echo OK", receiver, timeout, MILLISECONDS);
if (!"OK".equals(lastOutputLine)) {
throw new IOException("ADB command failed.");
}
Expand All @@ -309,7 +365,7 @@ static String escapeAndSingleQuote(String string) {
@FormatMethod
static String formatCommandWithArgs(String command, String... args) {
return String.format(
command, Arrays.stream(args).map(RemoteCommandExecutor::escapeAndSingleQuote).toArray());
command, stream(args).map(RemoteCommandExecutor::escapeAndSingleQuote).toArray());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.android.ddmlib.AdbCommandRejectedException;
import com.android.ddmlib.IDevice.DeviceState;
import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.InstallException;
import com.android.ddmlib.ShellCommandUnresponsiveException;
import com.android.ddmlib.SyncException;
import com.android.ddmlib.TimeoutException;
Expand Down Expand Up @@ -70,7 +69,9 @@ public abstract void executeShellCommand(
public abstract Path syncPackageToDevice(Path localFilePath)
throws TimeoutException, AdbCommandRejectedException, SyncException, IOException;

public abstract void removeRemotePackage(Path remoteFilePath) throws InstallException;
public abstract void removeRemotePath(
String remoteFilePath, Optional<String> runAsPackageName, Duration timeout)
throws IOException;

public abstract void pull(ImmutableList<FilePullParams> files);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,8 @@ public static String resolveLocalTestingPath(String localTestPath, Optional<Stri
.build());
return joinUnixPaths("/sdcard/Android/data/", packageNameStr, "files", localTestPath);
}

public static String getLocalTestingWorkingDir(String packageName) {
return joinUnixPaths("/data/data/", packageName, "files/splitcompat");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ private void writeToZipFile(ModuleSplit split, Path outputPath, TempDirectory te

// Invoke aapt2 to convert files from proto to binary format.
Path binaryApkPath = tempDir.getPath().resolve("binary.apk");
if (enableSparseEncoding) {
if (enableSparseEncoding && split.getResourceTable().isPresent()) {
Path interimApk = tempDir.getPath().resolve("interim.apk");
aapt2.convertApkProtoToBinary(partialProtoApk, interimApk);
aapt2.optimizeToSparseResourceTables(interimApk, binaryApkPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,16 +108,6 @@ public ModuleSplit mergeSingleShard(
createManifestMerger());
}

private AndroidManifestMerger createManifestMerger() {
if (FUSE_APPLICATION_ELEMENTS_FROM_FEATURE_MANIFESTS.enabledForVersion(bundletoolVersion)) {
return fusingMergerApplicationElements();
}
if (FUSE_ACTIVITIES_FROM_FEATURE_MANIFESTS.enabledForVersion(bundletoolVersion)) {
return fusingMergerOnlyReplaceActivities();
}
return useBaseModuleManifestMerger();
}

/**
* Gets a list of splits, and merges them into a single standalone APK (aka shard).
*
Expand Down Expand Up @@ -193,6 +183,16 @@ public ModuleSplit mergeSingleShard(
mergedSplitType);
}

private AndroidManifestMerger createManifestMerger() {
if (FUSE_APPLICATION_ELEMENTS_FROM_FEATURE_MANIFESTS.enabledForVersion(bundletoolVersion)) {
return fusingMergerApplicationElements();
}
if (FUSE_ACTIVITIES_FROM_FEATURE_MANIFESTS.enabledForVersion(bundletoolVersion)) {
return fusingMergerOnlyReplaceActivities();
}
return useBaseModuleManifestMerger();
}

/**
* Gets a list of collections of splits, and merges each collection into a single standalone APK
* (aka shard).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Range;
import com.google.common.primitives.Ints;
import com.google.errorprone.annotations.Immutable;
import java.util.Optional;
import java.util.stream.Stream;
Expand Down Expand Up @@ -320,10 +321,13 @@ public ImmutableList<String> getSupportsGlTextures() {
}

private static boolean isSdkCodename(String sdkVersion) {
if (sdkVersion.isEmpty()) {
return false;
}
// Codename version can be of the form "[codename]" or "[codename].[fingerprint]".
return !sdkVersion.isEmpty()
&& Range.closed('A', 'Z').contains(sdkVersion.charAt(0))
&& (sdkVersion.length() == 1 || '.' == sdkVersion.charAt(1));
int dotIndex = sdkVersion.indexOf('.');
String codename = dotIndex != -1 ? sdkVersion.substring(0, dotIndex) : sdkVersion;
return Ints.tryParse(codename) == null;
}

public boolean hasApplicationElement() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
*/
public final class BundleToolVersion {

private static final String CURRENT_VERSION = "1.8.0";
private static final String CURRENT_VERSION = "1.8.1";

/** Returns the version of BundleTool being run. */
public static Version getCurrentVersion() {
Expand Down
Loading

0 comments on commit 5ba6c05

Please sign in to comment.