Skip to content

Commit

Permalink
Prepare for release 1.15.0.
Browse files Browse the repository at this point in the history
  • Loading branch information
dovix91 committed May 9, 2023
1 parent 6a54377 commit 65ca3b5
Show file tree
Hide file tree
Showing 24 changed files with 827 additions and 10 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.14.1](https://github.com/google/bundletool/releases)
Latest release: [1.15.0](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.14.1
release_version = 1.15.0
Original file line number Diff line number Diff line change
Expand Up @@ -1505,7 +1505,7 @@ public static CommandHelp help() {
.setOptional(true)
.setDescription(
"When set, conditional modules with fused attribute will be fused into the"
+ " base module if they match the the device given by %s",
+ " base module if they match the device given by %s",
DEVICE_SPEC_FLAG.getName())
.build())
.addFlag(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ public abstract class InstallApksCommand {
private static final Flag<ImmutableSet<String>> MODULES_FLAG = Flag.stringSet("modules");
private static final Flag<Boolean> ALLOW_DOWNGRADE_FLAG = Flag.booleanFlag("allow-downgrade");
private static final Flag<Boolean> ALLOW_TEST_ONLY_FLAG = Flag.booleanFlag("allow-test-only");
private static final Flag<Boolean> GRANT_RUNTIME_PERMISSIONS_FLAG =
Flag.booleanFlag("grant-runtime-permissions");
private static final Flag<Integer> DEVICE_TIER_FLAG = Flag.nonNegativeInteger("device-tier");
private static final Flag<ImmutableSet<String>> DEVICE_GROUPS_FLAG =
Flag.stringSet("device-groups");
Expand All @@ -93,6 +95,8 @@ public abstract class InstallApksCommand {

public abstract boolean getAllowTestOnly();

public abstract boolean getGrantRuntimePermissions();

public abstract Optional<Integer> getDeviceTier();

public abstract Optional<ImmutableSet<String>> getDeviceGroups();
Expand All @@ -109,6 +113,7 @@ public static Builder builder() {
return new AutoValue_InstallApksCommand.Builder()
.setAllowDowngrade(false)
.setAllowTestOnly(false)
.setGrantRuntimePermissions(false)
.setTimeout(Device.DEFAULT_ADB_TIMEOUT);
}

Expand All @@ -130,6 +135,8 @@ public abstract static class Builder {

public abstract Builder setAllowTestOnly(boolean allowTestOnly);

public abstract Builder setGrantRuntimePermissions(boolean value);

public abstract Builder setDeviceTier(Integer deviceTier);

public abstract Builder setDeviceGroups(ImmutableSet<String> deviceGroups);
Expand Down Expand Up @@ -158,6 +165,7 @@ public static InstallApksCommand fromFlags(
Optional<ImmutableSet<String>> modules = MODULES_FLAG.getValue(flags);
Optional<Boolean> allowDowngrade = ALLOW_DOWNGRADE_FLAG.getValue(flags);
Optional<Boolean> allowTestOnly = ALLOW_TEST_ONLY_FLAG.getValue(flags);
Optional<Boolean> grantRuntimePermissions = GRANT_RUNTIME_PERMISSIONS_FLAG.getValue(flags);
Optional<Integer> deviceTier = DEVICE_TIER_FLAG.getValue(flags);
Optional<ImmutableSet<String>> deviceGroups = DEVICE_GROUPS_FLAG.getValue(flags);
Optional<String> countrySet = COUNTRY_SET_FLAG.getValue(flags);
Expand All @@ -173,6 +181,7 @@ public static InstallApksCommand fromFlags(
modules.ifPresent(command::setModules);
allowDowngrade.ifPresent(command::setAllowDowngrade);
allowTestOnly.ifPresent(command::setAllowTestOnly);
grantRuntimePermissions.ifPresent(command::setGrantRuntimePermissions);
deviceTier.ifPresent(command::setDeviceTier);
deviceGroups.ifPresent(command::setDeviceGroups);
countrySet.ifPresent(command::setCountrySet);
Expand Down Expand Up @@ -216,6 +225,7 @@ public void execute() {
InstallOptions.builder()
.setAllowDowngrade(getAllowDowngrade())
.setAllowTestOnly(getAllowTestOnly())
.setGrantRuntimePermissions(getGrantRuntimePermissions())
.setTimeout(getTimeout())
.build();

Expand Down Expand Up @@ -449,6 +459,14 @@ public static CommandHelp help() {
"If set, apps with 'android:testOnly=true' set in their manifest can also be"
+ " deployed")
.build())
.addFlag(
FlagDescription.builder()
.setFlagName(GRANT_RUNTIME_PERMISSIONS_FLAG.getName())
.setOptional(true)
.setDescription(
"If set, apps are granted runtime permissions. Available on API "
+ "level 23(Android M) and above.")
.build())
.addFlag(
FlagDescription.builder()
.setFlagName(DEVICE_TIER_FLAG.getName())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ public void installApks(ImmutableList<Path> apks, InstallOptions installOptions)
if (installOptions.getAllowTestOnly()) {
extraArgs.add("-t");
}
if (installOptions.getGrantRuntimePermissions()
&& device.getVersion().isGreaterOrEqualThan(AndroidVersion.VersionCodes.M)) {
extraArgs.add("-g");
}

try {
if (getVersion()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,16 @@ public abstract static class InstallOptions {

public abstract boolean getAllowTestOnly();

public abstract boolean getGrantRuntimePermissions();

public abstract Duration getTimeout();

public static Builder builder() {
return new AutoValue_Device_InstallOptions.Builder()
.setTimeout(DEFAULT_ADB_TIMEOUT)
.setAllowReinstall(true)
.setAllowDowngrade(false)
.setGrantRuntimePermissions(false)
.setAllowTestOnly(false);
}

Expand All @@ -108,6 +111,8 @@ public abstract static class Builder {

public abstract Builder setAllowTestOnly(boolean allowTestOnly);

public abstract Builder setGrantRuntimePermissions(boolean value);

public abstract InstallOptions build();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
Expand All @@ -50,7 +51,10 @@
*/
public final class ZipBuilder {
private static final long PRELOAD_INTO_MEMORY_THRESHOLD = 150 * 1024 * 1024L;
private static final long EPOCH = 0L;

/** Normalize timestamps. */
private static final long DEFAULT_TIMESTAMP =
new GregorianCalendar(2010, 0, 1, 0, 0, 0).getTimeInMillis();

/** Entries to be output. */
@GuardedBy("this")
Expand Down Expand Up @@ -78,13 +82,13 @@ public synchronized Path writeTo(Path target) throws IOException {
// For directories, we append "/" at the end of the file path since that's what the
// ZipEntry class relies on.
ZipEntry zipEntry = new ZipEntry(path + "/");
zipEntry.setTime(EPOCH);
zipEntry.setTime(DEFAULT_TIMESTAMP);
outZip.putNextEntry(zipEntry);
// Directories are represented as having empty content in a zip file, so we don't write
// any bytes to the outZip for this entry.
} else {
ZipEntry zipEntry = new ZipEntry(path.toString());
zipEntry.setTime(EPOCH);
zipEntry.setTime(DEFAULT_TIMESTAMP);
if (entry.hasOption(EntryOption.UNCOMPRESSED)) {
zipEntry.setMethod(ZipEntry.STORED);
// ZipFile API requires us to set the following properties manually for uncompressed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ public abstract class AndroidManifest {
"android.sdksandbox.PROPERTY_SDK_PROVIDER_CLASS_NAME";
public static final String COMPAT_SDK_PROVIDER_CLASS_NAME_ATTRIBUTE_NAME =
"android.sdksandbox.PROPERTY_COMPAT_SDK_PROVIDER_CLASS_NAME";
public static final String DECLARATIVE_WATCH_FACE_PROPERTY =
"com.google.wear.watchface.format.version";

public static final String REQUIRED_ATTRIBUTE_NAME = "required";
public static final int SDK_SANDBOX_MIN_VERSION = ANDROID_T_API_VERSION;
Expand Down Expand Up @@ -170,6 +172,7 @@ public abstract class AndroidManifest {
public static final String MODULE_TYPE_FEATURE_VALUE = "feature";
public static final String MODULE_TYPE_ASSET_VALUE = "asset-pack";
public static final String MODULE_TYPE_ML_VALUE = "ml-pack";
public static final String MODULE_TYPE_SDK_VALUE = "sdk";

/** <meta-data> name that specifies native library for native activity */
public static final String NATIVE_ACTIVITY_LIB_NAME = "android.app.lib_name";
Expand Down Expand Up @@ -465,6 +468,8 @@ private static ModuleType getModuleTypeFromAttributeValue(String value) {
return ModuleType.ASSET_MODULE;
case MODULE_TYPE_ML_VALUE:
return ModuleType.ML_MODULE;
case MODULE_TYPE_SDK_VALUE:
return ModuleType.SDK_DEPENDENCY_MODULE;
default:
throw InvalidBundleException.builder()
.withUserMessage("Found invalid type attribute %s for <module> element.", value)
Expand Down Expand Up @@ -943,6 +948,11 @@ public Optional<String> getCompatSdkProviderClassNameProperty() {
.map(XmlProtoAttribute::getValueAsString);
}

public Optional<String> getDeclarativeWatchFaceProperty() {
return getPropertyValue(DECLARATIVE_WATCH_FACE_PROPERTY)
.map(XmlProtoAttribute::getValueAsString);
}

/** Gets the AppComponentFactory class name if it is set in the AndroidManifest. */
public Optional<String> getAppComponentFactoryAttribute() {
return getApplicationAttribute(APP_COMPONENT_FACTORY_RESOURCE_ID)
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.model.utils.TargetingProtoUtils.sdkVersionFrom;
import static com.android.tools.build.bundletool.model.utils.TargetingProtoUtils.sdkVersionTargeting;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.util.function.Function.identity;
Expand All @@ -29,12 +30,15 @@
import com.android.bundle.Commands.FeatureModuleType;
import com.android.bundle.Commands.ModuleMetadata;
import com.android.bundle.Commands.RuntimeEnabledSdkDependency;
import com.android.bundle.Commands.SdkModuleMetadata;
import com.android.bundle.Commands.SdkModuleVersion;
import com.android.bundle.Config.ApexConfig;
import com.android.bundle.Config.BundleConfig.BundleType;
import com.android.bundle.Files.ApexImages;
import com.android.bundle.Files.Assets;
import com.android.bundle.Files.NativeLibraries;
import com.android.bundle.RuntimeEnabledSdkConfigProto.RuntimeEnabledSdkConfig;
import com.android.bundle.SdkModulesConfigOuterClass.RuntimeEnabledSdkVersion;
import com.android.bundle.SdkModulesConfigOuterClass.SdkModulesConfig;
import com.android.bundle.Targeting.ModuleTargeting;
import com.android.tools.build.bundletool.model.exceptions.InvalidBundleException;
Expand Down Expand Up @@ -277,8 +281,12 @@ public ModuleMetadata getModuleMetadata(boolean isSdkRuntimeVariant) {
.setTargeting(getModuleTargeting())
.setDeliveryType(moduleDeliveryTypeToDeliveryType(getDeliveryType()));

moduleTypeToFeatureModuleType(getModuleType())
.ifPresent(moduleType -> moduleMetadata.setModuleType(moduleType));
moduleTypeToFeatureModuleType(getModuleType()).ifPresent(moduleMetadata::setModuleType);
getSdkModulesConfig()
.ifPresent(
sdkModulesConfig ->
moduleMetadata.setSdkModuleMetadata(
sdkModulesConfigToSdkModuleMetadata(sdkModulesConfig)));
if (isSdkRuntimeVariant) {
getRuntimeEnabledSdkConfig()
.ifPresent(
Expand Down Expand Up @@ -318,8 +326,9 @@ private static DeliveryType moduleDeliveryTypeToDeliveryType(
private static Optional<FeatureModuleType> moduleTypeToFeatureModuleType(ModuleType moduleType) {
switch (moduleType) {
case FEATURE_MODULE:
case SDK_DEPENDENCY_MODULE:
return Optional.of(FeatureModuleType.FEATURE_MODULE);
case SDK_DEPENDENCY_MODULE:
return Optional.of(FeatureModuleType.SDK_MODULE);
case ML_MODULE:
return Optional.of(FeatureModuleType.ML_MODULE);
case ASSET_MODULE:
Expand All @@ -329,6 +338,24 @@ private static Optional<FeatureModuleType> moduleTypeToFeatureModuleType(ModuleT
throw new IllegalArgumentException("Unknown module type: " + moduleType);
}

private static SdkModuleMetadata sdkModulesConfigToSdkModuleMetadata(
SdkModulesConfig sdkModulesConfig) {
return SdkModuleMetadata.newBuilder()
.setSdkPackageName(sdkModulesConfig.getSdkPackageName())
.setSdkModuleVersion(
runtimeEnabledSdkVersionToModuleMetadataConverter(sdkModulesConfig.getSdkVersion()))
.build();
}

private static SdkModuleVersion runtimeEnabledSdkVersionToModuleMetadataConverter(
RuntimeEnabledSdkVersion runtimeEnabledSdkVersion) {
return SdkModuleVersion.newBuilder()
.setMajor(runtimeEnabledSdkVersion.getMajor())
.setMinor(runtimeEnabledSdkVersion.getMinor())
.setPatch(runtimeEnabledSdkVersion.getPatch())
.build();
}

public static Builder builder() {
return new AutoValue_BundleModule.Builder().setModuleType(ModuleType.UNKNOWN_MODULE_TYPE);
}
Expand Down Expand Up @@ -443,6 +470,10 @@ public final BundleModule build() {
.setModuleType(bundleModule.getAndroidManifest().getModuleType())
.build();
}
checkState(
!bundleModule.getModuleType().equals(ModuleType.SDK_DEPENDENCY_MODULE)
|| bundleModule.getSdkModulesConfig().isPresent(),
"BundleModule of type SDK_DEPENDENCY_MODULE can not have empty SdkModulesConfig.");
return bundleModule;
}
}
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.14.1";
private static final String CURRENT_VERSION = "1.15.0";

/** Returns the version of BundleTool being run. */
public static Version getCurrentVersion() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public class AppBundleValidator {
new AssetModuleFilesValidator(),
new CodeTransparencyValidator(),
new RuntimeEnabledSdkConfigValidator(),
new DeclarativeWatchFaceBundleValidator(),
new StandaloneFeatureModulesValidator());

private final ImmutableList<SubValidator> allBundleSubValidators;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,16 @@ public static boolean isAssetOnlyBundle(ImmutableList<BundleModule> modules) {
.equals(BundleConfig.BundleType.ASSET_ONLY);
}

public static boolean isDeclarativeWatchFaceBundle(AppBundle bundle) {
if (bundle.hasBaseModule()) {
Optional<String> dwfProperty =
bundle.getBaseModule().getAndroidManifest().getDeclarativeWatchFaceProperty();

return dwfProperty.isPresent();
}
return false;
}

public static BundleModule expectBaseModule(ImmutableList<BundleModule> modules) {
return modules.stream()
.filter(BundleModule::isBaseModule)
Expand Down
Loading

0 comments on commit 65ca3b5

Please sign in to comment.