From 0b00e4a8d3129cdfa2a98119fe7a3373ff49cdd3 Mon Sep 17 00:00:00 2001 From: sopo Date: Tue, 7 Nov 2023 17:23:58 +0000 Subject: [PATCH] Prepare for release 1.15.6. --- README.md | 2 +- build.gradle | 12 +++-- gradle.properties | 2 +- .../archive/ArchivedAndroidManifestUtils.java | 54 ++++++++++--------- .../archive/ArchivedApksGenerator.java | 12 ++--- .../bundletool/commands/BuildApksModule.java | 15 +++--- .../commands/BuildSdkApksCommand.java | 7 +++ .../commands/BuildSdkApksManager.java | 7 +++ .../bundletool/io/ModuleSplitSerializer.java | 24 +++++++-- .../bundletool/model/ManifestEditor.java | 9 ++++ .../build/bundletool/model/ModuleSplit.java | 7 +++ .../model/manifestelements/Activity.java | 30 +++++++++++ .../model/version/BundleToolVersion.java | 2 +- .../splitters/SdkRuntimeVariantGenerator.java | 12 ++--- src/main/proto/config.proto | 16 ++++++ .../commands/BuildApksManagerTest.java | 4 +- .../commands/BuildSdkApksManagerTest.java | 36 +++++++++++++ .../bundletool/model/ManifestEditorTest.java | 25 +++++++++ .../SdkRuntimeVariantGeneratorTest.java | 46 ++++++++-------- .../splitters/SplitApksGeneratorTest.java | 22 ++++---- .../bundletool/testing/TargetingUtils.java | 3 +- 21 files changed, 254 insertions(+), 93 deletions(-) diff --git a/README.md b/README.md index 01dfb124..c7416b18 100644 --- a/README.md +++ b/README.md @@ -46,4 +46,4 @@ https://developer.android.com/studio/command-line/bundletool ## Releases -Latest release: [1.15.5](https://github.com/google/bundletool/releases) +Latest release: [1.15.6](https://github.com/google/bundletool/releases) diff --git a/build.gradle b/build.gradle index 83535794..2676cb2c 100644 --- a/build.gradle +++ b/build.gradle @@ -120,7 +120,9 @@ test { } reports { - html.enabled = false + html { + enabled false + } } } @@ -175,8 +177,8 @@ publishing { // Artifact released to Maven. shadowJar { - baseName = 'bundletool' - classifier = '' + archiveBaseName = 'bundletool' + archiveClassifier = '' // Package all the Android Gradle plugin dependencies that are compiled from // source. @@ -211,8 +213,8 @@ shadowJar { // Artifact to use as standalone command line tool. task executableJar(type: ShadowJar) { - baseName = 'bundletool' - classifier = 'all' + archiveBaseName = 'bundletool' + archiveClassifier = 'all' from sourceSets.main.output from({ zipTree(project.configurations.implementationWindows.singleFile) }) { into 'windows/' } from({ zipTree(project.configurations.implementationMacOs.singleFile) }) { into 'macos/' } diff --git a/gradle.properties b/gradle.properties index f1be7d20..bf6979d8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -release_version = 1.15.5 +release_version = 1.15.6 diff --git a/src/main/java/com/android/tools/build/bundletool/archive/ArchivedAndroidManifestUtils.java b/src/main/java/com/android/tools/build/bundletool/archive/ArchivedAndroidManifestUtils.java index d939877c..1e401306 100644 --- a/src/main/java/com/android/tools/build/bundletool/archive/ArchivedAndroidManifestUtils.java +++ b/src/main/java/com/android/tools/build/bundletool/archive/ArchivedAndroidManifestUtils.java @@ -35,11 +35,13 @@ import com.android.tools.build.bundletool.model.manifestelements.Activity; import com.android.tools.build.bundletool.model.manifestelements.IntentFilter; import com.android.tools.build.bundletool.model.manifestelements.Receiver; +import com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoAttribute; import com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoElementBuilder; import com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoNode; import com.android.tools.build.bundletool.model.version.BundleToolVersion; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import java.util.Optional; /** Utility methods for creation of archived manifest. */ public final class ArchivedAndroidManifestUtils { @@ -91,7 +93,7 @@ public final class ArchivedAndroidManifestUtils { AndroidManifest.PERMISSION_TREE_ELEMENT_NAME); public static AndroidManifest createArchivedManifest( - AndroidManifest manifest, boolean createDifferentThemesForTvAndPhone) { + AndroidManifest manifest, boolean removeTvIconCloud) { checkNotNull(manifest); ManifestEditor editor = @@ -131,7 +133,7 @@ public static AndroidManifest createArchivedManifest( CHILDREN_ELEMENTS_TO_KEEP.forEach( elementName -> editor.copyChildrenElements(manifest, elementName)); - if (createDifferentThemesForTvAndPhone) { + if (removeTvIconCloud) { if (manifest.hasMainActivity()) { editor.addActivity( createReactivateActivity( @@ -146,7 +148,9 @@ public static AndroidManifest createArchivedManifest( IntentFilter.builder() .addActionName(MAIN_ACTION_NAME) .addCategoryName(LEANBACK_LAUNCHER_CATEGORY_NAME) - .build())); + .build(), + manifest.getIconAttribute().map(XmlProtoAttribute::getValueAsRefId), + manifest.getRoundIconAttribute().map(XmlProtoAttribute::getValueAsRefId))); } } else { editor.addActivity(createReactivateActivity(manifest)); @@ -168,7 +172,7 @@ private static XmlProtoNode createMinimalManifestTag() { public static AndroidManifest updateArchivedIconsAndTheme( AndroidManifest manifest, ImmutableMap resourceNameToIdMap, - boolean createDifferentThemesForTvAndPhone) { + boolean removeTvIconCloud) { ManifestEditor archivedManifestEditor = manifest.toEditor(); if (manifest.getIconAttribute().isPresent() @@ -182,20 +186,9 @@ public static AndroidManifest updateArchivedIconsAndTheme( resourceNameToIdMap.get(ARCHIVED_ROUND_ICON_DRAWABLE_NAME)); } - if (createDifferentThemesForTvAndPhone) { - if (manifest.hasMainActivity()) { - archivedManifestEditor.setActivityTheme( - REACTIVATE_ACTIVITY_NAME, - LAUNCHER_CATEGORY_NAME, - HOLO_LIGHT_NO_ACTION_BAR_FULSCREEN_THEME_RESOURCE_ID); - } - if (manifest.hasMainTvActivity()) { - archivedManifestEditor.setActivityTheme( - REACTIVATE_ACTIVITY_NAME, - LEANBACK_LAUNCHER_CATEGORY_NAME, - checkNotNull(resourceNameToIdMap.get(ArchivedResourcesHelper.ARCHIVED_TV_THEME_NAME)) - .intValue()); - } + if (removeTvIconCloud) { + archivedManifestEditor.setApplicationTheme( + resourceNameToIdMap.get(ArchivedResourcesHelper.ARCHIVED_TV_THEME_NAME)); } else { archivedManifestEditor.setActivityTheme( REACTIVATE_ACTIVITY_NAME, @@ -205,17 +198,21 @@ public static AndroidManifest updateArchivedIconsAndTheme( return archivedManifestEditor.save(); } - private static Activity createReactivateActivity(IntentFilter intentFilter) { - return Activity.builder() + + private static Activity createReactivateActivity( + IntentFilter intentFilter, Optional icon, Optional roundIcon) { + return getCommonActivityBuilder() .setName(REACTIVATE_ACTIVITY_NAME) - .setExported(true) - .setExcludeFromRecents(true) - .setStateNotNeeded(true) - .setNoHistory(true) .setIntentFilter(intentFilter) + .setIcon(icon) + .setRoundIcon(roundIcon) .build(); } + private static Activity createReactivateActivity(IntentFilter intentFilter) { + return getCommonActivityBuilder().setIntentFilter(intentFilter).build(); + } + private static Activity createReactivateActivity(AndroidManifest manifest) { IntentFilter.Builder intentFilterBuilder = IntentFilter.builder().addActionName(MAIN_ACTION_NAME); @@ -239,6 +236,15 @@ private static Activity createReactivateActivity(AndroidManifest manifest) { .build(); } + private static Activity.Builder getCommonActivityBuilder() { + return Activity.builder() + .setName(REACTIVATE_ACTIVITY_NAME) + .setExported(true) + .setExcludeFromRecents(true) + .setStateNotNeeded(true) + .setNoHistory(true); + } + private static Receiver createUpdateBroadcastReceiver() { return Receiver.builder() .setName(UPDATE_BROADCAST_RECEIVER_NAME) diff --git a/src/main/java/com/android/tools/build/bundletool/archive/ArchivedApksGenerator.java b/src/main/java/com/android/tools/build/bundletool/archive/ArchivedApksGenerator.java index 6ebe14d5..e251c09f 100644 --- a/src/main/java/com/android/tools/build/bundletool/archive/ArchivedApksGenerator.java +++ b/src/main/java/com/android/tools/build/bundletool/archive/ArchivedApksGenerator.java @@ -19,7 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.android.aapt.Resources.ResourceTable; -import com.android.tools.build.bundletool.commands.BuildApksModule.DifferentThemesForTvAndPhone; +import com.android.tools.build.bundletool.commands.BuildApksModule.RemoveTvIconCloud; import com.android.tools.build.bundletool.io.ResourceReader; import com.android.tools.build.bundletool.model.AndroidManifest; import com.android.tools.build.bundletool.model.AppBundle; @@ -49,13 +49,13 @@ public final class ArchivedApksGenerator { private final ResourceReader resourceReader; private final ArchivedResourcesHelper archivedResourcesHelper; - private final boolean createDifferentThemesForTvAndPhone; + private final boolean removeTvIconCloud; @Inject - ArchivedApksGenerator(@DifferentThemesForTvAndPhone boolean createDifferentThemesForTvAndPhone) { + ArchivedApksGenerator(@RemoveTvIconCloud boolean removeTvIconCloud) { resourceReader = new ResourceReader(); archivedResourcesHelper = new ArchivedResourcesHelper(resourceReader); - this.createDifferentThemesForTvAndPhone = createDifferentThemesForTvAndPhone; + this.removeTvIconCloud = removeTvIconCloud; } public ModuleSplit generateArchivedApk( @@ -66,7 +66,7 @@ public ModuleSplit generateArchivedApk( AndroidManifest archivedManifest = ArchivedAndroidManifestUtils.createArchivedManifest( - baseModule.getAndroidManifest(), createDifferentThemesForTvAndPhone); + baseModule.getAndroidManifest(), removeTvIconCloud); ResourceTable archivedResourceTable = getArchivedResourceTable(appBundle, baseModule, archivedManifest); @@ -91,7 +91,7 @@ public ModuleSplit generateArchivedApk( archivedManifest = ArchivedAndroidManifestUtils.updateArchivedIconsAndTheme( - archivedManifest, extraResourceNameToIdMap, createDifferentThemesForTvAndPhone); + archivedManifest, extraResourceNameToIdMap, removeTvIconCloud); ModuleSplit moduleSplit = ModuleSplit.forArchive( diff --git a/src/main/java/com/android/tools/build/bundletool/commands/BuildApksModule.java b/src/main/java/com/android/tools/build/bundletool/commands/BuildApksModule.java index 619e4cd0..4205ccdf 100644 --- a/src/main/java/com/android/tools/build/bundletool/commands/BuildApksModule.java +++ b/src/main/java/com/android/tools/build/bundletool/commands/BuildApksModule.java @@ -174,11 +174,11 @@ static Optional provideLocalRuntimeEnabl @CommandScoped @Provides - @DifferentThemesForTvAndPhone - static boolean provideDifferentThemesForTvAndPhone(BuildApksCommand command) { + @RemoveTvIconCloud + static boolean provideRemoveTvIconCloud(BuildApksCommand command) { @SuppressWarnings("unused") - boolean differentThemesForTvAndPhone = false; - return differentThemesForTvAndPhone; + boolean removeTvIconCloud = false; + return removeTvIconCloud; } /** @@ -207,13 +207,10 @@ static boolean provideDifferentThemesForTvAndPhone(BuildApksCommand command) { @Retention(RUNTIME) public @interface ApkSigningConfigProvider {} - /** - * Qualifying annotation of a {@code boolean} to enable usage of different themes for tv and - * phone. - */ + /** Qualifying annotation of a {@code boolean} to enable removing the icon's cloud for TV. */ @Qualifier @Retention(RUNTIME) - public @interface DifferentThemesForTvAndPhone {} + public @interface RemoveTvIconCloud {} private BuildApksModule() {} } diff --git a/src/main/java/com/android/tools/build/bundletool/commands/BuildSdkApksCommand.java b/src/main/java/com/android/tools/build/bundletool/commands/BuildSdkApksCommand.java index 2958d3b3..2c6a9a9e 100644 --- a/src/main/java/com/android/tools/build/bundletool/commands/BuildSdkApksCommand.java +++ b/src/main/java/com/android/tools/build/bundletool/commands/BuildSdkApksCommand.java @@ -127,6 +127,8 @@ ListeningExecutorService getExecutorService() { public abstract Optional getFirstVariantNumber(); + public abstract Optional getMinSdkVersion(); + /** Creates a builder for the {@link BuildSdkApksCommand} with some default settings. */ public static BuildSdkApksCommand.Builder builder() { return new AutoValue_BuildSdkApksCommand.Builder() @@ -136,6 +138,8 @@ public static BuildSdkApksCommand.Builder builder() { .setVerbose(false); } + public abstract Builder toBuilder(); + /** Builder for the {@link BuildSdkApksCommand}. */ @AutoValue.Builder public abstract static class Builder { @@ -231,6 +235,9 @@ public Builder setExecutorService(ListeningExecutorService executorService) { public abstract Builder setFirstVariantNumber(int firstVariantNumber); + /** Overrides value of android:minSdkVersion attribute in the generated APKs. */ + public abstract Builder setMinSdkVersion(int minSdkVersion); + abstract BuildSdkApksCommand autoBuild(); /** diff --git a/src/main/java/com/android/tools/build/bundletool/commands/BuildSdkApksManager.java b/src/main/java/com/android/tools/build/bundletool/commands/BuildSdkApksManager.java index e46dabc2..a30b53fe 100644 --- a/src/main/java/com/android/tools/build/bundletool/commands/BuildSdkApksManager.java +++ b/src/main/java/com/android/tools/build/bundletool/commands/BuildSdkApksManager.java @@ -99,6 +99,7 @@ private ImmutableList generateSdkApks() { moduleSplit.writeSdkLibraryElement( sdkBundle.getPackageName(), sdkBundle.getSdkAndroidVersionMajor())) .map(ModuleSplit::overrideMinSdkVersionForSdkSandbox) + .map(moduleSplit -> overrideMinSdkVersion(moduleSplit)) .map(moduleSplit -> moduleSplit.writePatchVersion(sdkBundle.getPatchVersion())) .map(moduleSplit -> moduleSplit.writeSdkProviderClassName(sdkBundle.getProviderClassName())) .map(this::writeCompatSdkProviderClassNameIfPresent) @@ -107,6 +108,12 @@ private ImmutableList generateSdkApks() { .collect(toImmutableList()); } + private ModuleSplit overrideMinSdkVersion(ModuleSplit moduleSplit) { + return command.getMinSdkVersion().isPresent() + ? moduleSplit.overrideMinSdkVersion(command.getMinSdkVersion().get()) + : moduleSplit.overrideMinSdkVersionForSdkSandbox(); + } + private ModuleSplit writeCompatSdkProviderClassNameIfPresent(ModuleSplit moduleSplit) { if (sdkBundle.getCompatProviderClassName().isPresent()) { return moduleSplit.writeCompatSdkProviderClassName( diff --git a/src/main/java/com/android/tools/build/bundletool/io/ModuleSplitSerializer.java b/src/main/java/com/android/tools/build/bundletool/io/ModuleSplitSerializer.java index bbb63742..b6a43fae 100644 --- a/src/main/java/com/android/tools/build/bundletool/io/ModuleSplitSerializer.java +++ b/src/main/java/com/android/tools/build/bundletool/io/ModuleSplitSerializer.java @@ -70,6 +70,7 @@ public class ModuleSplitSerializer extends ApkSerializer { private final ListeningExecutorService executorService; private final boolean use7ZipCompression; private final Optional p7ZipCommand; + private final int nativeLibraryAlignment; @Inject ModuleSplitSerializer( @@ -97,6 +98,7 @@ public class ModuleSplitSerializer extends ApkSerializer { this.bundletoolVersion = bundletoolVersion; this.executorService = executorService; this.p7ZipCommand = p7ZipCommand; + this.nativeLibraryAlignment = getNativeLibraryAlignment(bundleConfig); } /** @@ -105,6 +107,7 @@ public class ModuleSplitSerializer extends ApkSerializer { *

Returns {@link ApkDescription} for each serialized split keyed by relative path of module * split. */ + @Override public ImmutableMap serialize( Path outputDirectory, ImmutableMap splitsByRelativePath) { // Prepare original splits by: @@ -301,12 +304,13 @@ private void serializeSplit( *

Uncompressed native libraries inside APK must be aligned by 4096 and all other uncompressed * entries aligned by 4 bytes. */ - private static long alignmentForEntry( - ModuleEntry entry, ModuleEntriesPack uncompressedEntriesPack) { + private long alignmentForEntry(ModuleEntry entry, ModuleEntriesPack uncompressedEntriesPack) { if (!uncompressedEntriesPack.hasEntry(entry)) { return 0; } - return entry.getPath().toString().endsWith(NATIVE_LIBRARIES_SUFFIX) ? 4096 : 4; + return entry.getPath().toString().endsWith(NATIVE_LIBRARIES_SUFFIX) + ? nativeLibraryAlignment + : 4; } /** @@ -408,4 +412,18 @@ private boolean shouldUncompressBecauseOfLowRatio( } return compressedSize >= uncompressedSize; } + + private int getNativeLibraryAlignment(BundleConfig bundleConfig) { + switch (bundleConfig.getOptimizations().getUncompressNativeLibraries().getAlignment()) { + case PAGE_ALIGNMENT_16K: + return 16384; + case PAGE_ALIGNMENT_64K: + return 65536; + case PAGE_ALIGNMENT_UNSPECIFIED: + case PAGE_ALIGNMENT_4K: + case UNRECOGNIZED: + return 4096; + } + throw new IllegalArgumentException("Wrong native libraries alignment."); + } } diff --git a/src/main/java/com/android/tools/build/bundletool/model/ManifestEditor.java b/src/main/java/com/android/tools/build/bundletool/model/ManifestEditor.java index 3f200863..68e97116 100644 --- a/src/main/java/com/android/tools/build/bundletool/model/ManifestEditor.java +++ b/src/main/java/com/android/tools/build/bundletool/model/ManifestEditor.java @@ -457,6 +457,15 @@ public ManifestEditor setActivityTheme(String activityName, int themeResId) { return this; } + @CanIgnoreReturnValue + public ManifestEditor setApplicationTheme(int themeResId) { + manifestElement + .getOrCreateChildElement(APPLICATION_ELEMENT_NAME) + .getOrCreateAndroidAttribute(THEME_ATTRIBUTE_NAME, THEME_RESOURCE_ID) + .setValueAsRefId(themeResId); + return this; + } + /** * Sets the theme of an activity that has an action with the name mainActionCategoryName to the * given themeResId. This method assumes such activity exists. diff --git a/src/main/java/com/android/tools/build/bundletool/model/ModuleSplit.java b/src/main/java/com/android/tools/build/bundletool/model/ModuleSplit.java index 772c27fb..9b7dd117 100644 --- a/src/main/java/com/android/tools/build/bundletool/model/ModuleSplit.java +++ b/src/main/java/com/android/tools/build/bundletool/model/ModuleSplit.java @@ -378,6 +378,13 @@ public ModuleSplit overrideMinSdkVersionForSdkSandbox() { return this; } + /** Overrides value of android:minSdkVersion attribute in the manifest. */ + public ModuleSplit overrideMinSdkVersion(int minSdkVersion) { + AndroidManifest apkManifest = + getAndroidManifest().toEditor().setMinSdkVersion(minSdkVersion).save(); + return toBuilder().setAndroidManifest(apkManifest).build(); + } + /** Writes the SDK Patch version to a new element. */ public ModuleSplit writePatchVersion(int patchVersion) { AndroidManifest apkManifest = diff --git a/src/main/java/com/android/tools/build/bundletool/model/manifestelements/Activity.java b/src/main/java/com/android/tools/build/bundletool/model/manifestelements/Activity.java index 48856315..484bf26c 100644 --- a/src/main/java/com/android/tools/build/bundletool/model/manifestelements/Activity.java +++ b/src/main/java/com/android/tools/build/bundletool/model/manifestelements/Activity.java @@ -19,8 +19,12 @@ import static com.android.tools.build.bundletool.model.AndroidManifest.ACTIVITY_ELEMENT_NAME; import static com.android.tools.build.bundletool.model.AndroidManifest.EXPORTED_ATTRIBUTE_NAME; import static com.android.tools.build.bundletool.model.AndroidManifest.EXPORTED_RESOURCE_ID; +import static com.android.tools.build.bundletool.model.AndroidManifest.ICON_ATTRIBUTE_NAME; +import static com.android.tools.build.bundletool.model.AndroidManifest.ICON_RESOURCE_ID; import static com.android.tools.build.bundletool.model.AndroidManifest.NAME_ATTRIBUTE_NAME; import static com.android.tools.build.bundletool.model.AndroidManifest.NAME_RESOURCE_ID; +import static com.android.tools.build.bundletool.model.AndroidManifest.ROUND_ICON_ATTRIBUTE_NAME; +import static com.android.tools.build.bundletool.model.AndroidManifest.ROUND_ICON_RESOURCE_ID; import static com.android.tools.build.bundletool.model.AndroidManifest.THEME_ATTRIBUTE_NAME; import static com.android.tools.build.bundletool.model.AndroidManifest.THEME_RESOURCE_ID; @@ -62,6 +66,10 @@ public abstract class Activity { abstract Optional getIntentFilter(); + abstract Optional getIcon(); + + abstract Optional getRoundIcon(); + public static Builder builder() { return new AutoValue_Activity.Builder(); } @@ -76,6 +84,8 @@ public XmlProtoElement asXmlProtoElement() { setStateNotNeeded(elementBuilder); setNoHistory(elementBuilder); setIntentFilterElement(elementBuilder); + setIconAttribute(elementBuilder); + setRoundIconAttribute(elementBuilder); return elementBuilder.build(); } @@ -134,6 +144,22 @@ private void setIntentFilterElement(XmlProtoElementBuilder elementBuilder) { } } + private void setIconAttribute(XmlProtoElementBuilder elementBuilder) { + if (getIcon().isPresent()) { + elementBuilder + .getOrCreateAndroidAttribute(ICON_ATTRIBUTE_NAME, ICON_RESOURCE_ID) + .setValueAsRefId(getIcon().get()); + } + } + + private void setRoundIconAttribute(XmlProtoElementBuilder elementBuilder) { + if (getRoundIcon().isPresent()) { + elementBuilder + .getOrCreateAndroidAttribute(ROUND_ICON_ATTRIBUTE_NAME, ROUND_ICON_RESOURCE_ID) + .setValueAsRefId(getRoundIcon().get()); + } + } + /** Builder for Activity. */ @AutoValue.Builder public abstract static class Builder { @@ -151,6 +177,10 @@ public abstract static class Builder { public abstract Builder setIntentFilter(IntentFilter intentFilter); + public abstract Builder setIcon(Optional iconResId); + + public abstract Builder setRoundIcon(Optional roundIconResId); + public abstract Activity build(); } } diff --git a/src/main/java/com/android/tools/build/bundletool/model/version/BundleToolVersion.java b/src/main/java/com/android/tools/build/bundletool/model/version/BundleToolVersion.java index 9abf9e71..74822589 100644 --- a/src/main/java/com/android/tools/build/bundletool/model/version/BundleToolVersion.java +++ b/src/main/java/com/android/tools/build/bundletool/model/version/BundleToolVersion.java @@ -26,7 +26,7 @@ */ public final class BundleToolVersion { - private static final String CURRENT_VERSION = "1.15.5"; + private static final String CURRENT_VERSION = "1.15.6"; /** Returns the version of BundleTool being run. */ diff --git a/src/main/java/com/android/tools/build/bundletool/splitters/SdkRuntimeVariantGenerator.java b/src/main/java/com/android/tools/build/bundletool/splitters/SdkRuntimeVariantGenerator.java index 5d6aa6a2..9719746b 100644 --- a/src/main/java/com/android/tools/build/bundletool/splitters/SdkRuntimeVariantGenerator.java +++ b/src/main/java/com/android/tools/build/bundletool/splitters/SdkRuntimeVariantGenerator.java @@ -15,16 +15,16 @@ */ package com.android.tools.build.bundletool.splitters; +import static com.android.tools.build.bundletool.model.AndroidManifest.SDK_SANDBOX_MIN_VERSION; import static com.android.tools.build.bundletool.model.utils.TargetingProtoUtils.sdkVersionFrom; -import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_T_API_VERSION; import static com.google.common.collect.ImmutableSet.toImmutableSet; import com.android.bundle.Targeting.SdkVersion; import com.android.bundle.Targeting.SdkVersionTargeting; import com.android.bundle.Targeting.VariantTargeting; +import com.android.tools.build.bundletool.model.AndroidManifest; import com.android.tools.build.bundletool.model.AppBundle; import com.android.tools.build.bundletool.model.utils.TargetingProtoUtils; -import com.android.tools.build.bundletool.model.utils.Versions; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Streams; import java.util.stream.Stream; @@ -49,8 +49,8 @@ public final class SdkRuntimeVariantGenerator { * *

This method generates a new {@link VariantTargeting} for each element of {@code * sdkVersionVariantTargetings} that targets SDK version higher than {@link - * Versions#ANDROID_T_API_VERSION}, as well as one variant targeting {@link - * Versions#ANDROID_T_API_VERSION}. + * AndroidManifest#SDK_SANDBOX_MIN_VERSION}, as well as one variant targeting {@link + * AndroidManifest#SDK_SANDBOX_MIN_VERSION}. * *

For example, if {@code sdkVersionVariantTargetings} contains 2 variants: targeting Android S * API and Android U API, the method will return 2 new variants: targeting Android T API and @@ -64,7 +64,7 @@ public ImmutableSet generate( ImmutableSet sdkVersions = Streams.concat( - Stream.of(sdkVersionFrom(ANDROID_T_API_VERSION)), + Stream.of(sdkVersionFrom(SDK_SANDBOX_MIN_VERSION)), sdkVersionVariantTargetings.stream() .filter( variantTargeting -> @@ -73,7 +73,7 @@ public ImmutableSet generate( .getValue(0) .getMin() .getValue() - > ANDROID_T_API_VERSION) + > SDK_SANDBOX_MIN_VERSION) .map(VariantTargeting::getSdkVersionTargeting) .flatMap(sdkVersionTargeting -> sdkVersionTargeting.getValueList().stream())) .collect(toImmutableSet()); diff --git a/src/main/proto/config.proto b/src/main/proto/config.proto index 3b3f3ac7..15a76c54 100644 --- a/src/main/proto/config.proto +++ b/src/main/proto/config.proto @@ -173,6 +173,22 @@ message ResourceOptimizations { message UncompressNativeLibraries { bool enabled = 1; + + enum PageAlignment { + PAGE_ALIGNMENT_UNSPECIFIED = 0; + PAGE_ALIGNMENT_4K = 1; + PAGE_ALIGNMENT_16K = 2; + PAGE_ALIGNMENT_64K = 3; + } + + // This is an experimental setting. It's behavior might be changed or + // completely removed. + // + // Alignment used for uncompressed native libraries inside APKs generated + // by bundletool. + // + // PAGE_ALIGNMENT_4K by default. + PageAlignment alignment = 2; } message UncompressDexFiles { diff --git a/src/test/java/com/android/tools/build/bundletool/commands/BuildApksManagerTest.java b/src/test/java/com/android/tools/build/bundletool/commands/BuildApksManagerTest.java index 2a23a09e..13a9df8c 100644 --- a/src/test/java/com/android/tools/build/bundletool/commands/BuildApksManagerTest.java +++ b/src/test/java/com/android/tools/build/bundletool/commands/BuildApksManagerTest.java @@ -50,7 +50,7 @@ import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_Q_API_VERSION; import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_S_API_VERSION; import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_S_V2_API_VERSION; -import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_T_API_VERSION; +import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_U_API_VERSION; import static com.android.tools.build.bundletool.testing.ApkSetUtils.extractFromApkSetFile; import static com.android.tools.build.bundletool.testing.ApkSetUtils.extractTocFromApkSetFile; import static com.android.tools.build.bundletool.testing.ApkSetUtils.parseTocFromFile; @@ -7238,7 +7238,7 @@ public void appBundleHasRuntimeEnabledSdkDeps_generatesSdkRuntimeVariant() throw assertThat(sdkRuntimeVariant.getVariantNumber()).isEqualTo(1); assertThat(sdkRuntimeVariant.getTargeting()) .isEqualTo( - sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION).toBuilder() + sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION).toBuilder() .setSdkRuntimeTargeting( SdkRuntimeTargeting.newBuilder().setRequiresSdkRuntime(true)) .build()); diff --git a/src/test/java/com/android/tools/build/bundletool/commands/BuildSdkApksManagerTest.java b/src/test/java/com/android/tools/build/bundletool/commands/BuildSdkApksManagerTest.java index b810b673..a7c6119d 100644 --- a/src/test/java/com/android/tools/build/bundletool/commands/BuildSdkApksManagerTest.java +++ b/src/test/java/com/android/tools/build/bundletool/commands/BuildSdkApksManagerTest.java @@ -21,6 +21,7 @@ import static com.android.tools.build.bundletool.model.AndroidManifest.VERSION_CODE_RESOURCE_ID; import static com.android.tools.build.bundletool.model.AndroidManifest.VERSION_MAJOR_RESOURCE_ID; import static com.android.tools.build.bundletool.model.AndroidManifest.VERSION_NAME_RESOURCE_ID; +import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_T_API_VERSION; import static com.android.tools.build.bundletool.testing.ApkSetUtils.extractFromApkSetFile; import static com.android.tools.build.bundletool.testing.ApkSetUtils.extractTocFromSdkApkSetFile; import static com.android.tools.build.bundletool.testing.ManifestProtoUtils.androidManifest; @@ -223,6 +224,41 @@ public void manifestIsMutated() throws Exception { assertThat(manifest.getCompatSdkProviderClassNameProperty()).isEmpty(); } + @Test + public void manifestIsMutated_nonDefaultMinSdkVersionSetInCommand() throws Exception { + Integer versionCode = 1253; + String packageName = "com.ads.foo"; + int major = 15; + int minor = 0; + int patch = 5; + String sdkProviderClassName = "com.example.sandboxservice.MyNewAdsSdkEntryPoint"; + SdkBundle sdkBundle = + new SdkBundleBuilder() + .setVersionCode(versionCode) + .setSdkModulesConfig( + createSdkModulesConfig() + .setSdkPackageName(packageName) + .setSdkVersion( + RuntimeEnabledSdkVersion.newBuilder() + .setMajor(major) + .setMinor(minor) + .setPatch(patch)) + .setSdkProviderClassName(sdkProviderClassName) + .build()) + .build(); + + execute(sdkBundle, createCommand().toBuilder().setMinSdkVersion(ANDROID_T_API_VERSION).build()); + + ZipFile apkSetFile = new ZipFile(outputFilePath.toFile()); + BuildSdkApksResult result = extractTocFromSdkApkSetFile(apkSetFile, tmpDir); + Variant variant = result.getVariant(0); + ApkDescription apkDescription = variant.getApkSet(0).getApkDescription(0); + File apkFile = extractFromApkSetFile(apkSetFile, apkDescription.getPath(), tmpDir); + AndroidManifest manifest = extractAndroidManifest(apkFile, tmpDir); + + assertThat(manifest.getMinSdkVersion()).hasValue(ANDROID_T_API_VERSION); + } + @Test public void sdkManifestMutation_highMinSdkVersion_minSdkVersionUnchanged() throws Exception { SdkBundle sdkBundle = diff --git a/src/test/java/com/android/tools/build/bundletool/model/ManifestEditorTest.java b/src/test/java/com/android/tools/build/bundletool/model/ManifestEditorTest.java index b0717b22..c0a75cf0 100644 --- a/src/test/java/com/android/tools/build/bundletool/model/ManifestEditorTest.java +++ b/src/test/java/com/android/tools/build/bundletool/model/ManifestEditorTest.java @@ -1652,6 +1652,31 @@ public void setActivityTheme_succeeds() { assertThat(edited).isEqualTo(expected); } + @Test + public void setApplicationTheme_succeeds() { + XmlNode application = xmlNode(xmlElement(APPLICATION_ELEMENT_NAME)); + AndroidManifest androidManifest = + AndroidManifest.create(xmlNode(xmlElement("manifest", application))); + + AndroidManifest edited = androidManifest.toEditor().setApplicationTheme(1).save(); + + AndroidManifest expected = + AndroidManifest.create( + xmlNode( + xmlElement( + "manifest", + xmlNode( + xmlElement( + APPLICATION_ELEMENT_NAME, + ImmutableList.of( + xmlResourceReferenceAttribute( + ANDROID_NAMESPACE_URI, + THEME_ATTRIBUTE_NAME, + THEME_RESOURCE_ID, + /* valueResourceId= */ 1))))))); + assertThat(edited).isEqualTo(expected); + } + @Test public void updateApplicationElement_succeeds() { XmlNode oldApplication = diff --git a/src/test/java/com/android/tools/build/bundletool/splitters/SdkRuntimeVariantGeneratorTest.java b/src/test/java/com/android/tools/build/bundletool/splitters/SdkRuntimeVariantGeneratorTest.java index 48a7cf6c..f4406bb6 100644 --- a/src/test/java/com/android/tools/build/bundletool/splitters/SdkRuntimeVariantGeneratorTest.java +++ b/src/test/java/com/android/tools/build/bundletool/splitters/SdkRuntimeVariantGeneratorTest.java @@ -15,9 +15,9 @@ */ package com.android.tools.build.bundletool.splitters; -import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_R_API_VERSION; import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_S_API_VERSION; import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_T_API_VERSION; +import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_U_API_VERSION; import static com.android.tools.build.bundletool.testing.ManifestProtoUtils.androidManifest; import static com.android.tools.build.bundletool.testing.TargetingUtils.sdkRuntimeVariantTargeting; import static com.android.tools.build.bundletool.testing.TargetingUtils.variantMinSdkTargeting; @@ -65,7 +65,7 @@ public void bundleHasRuntimeEnabledSdkDeps_generatesSdkRuntimeVariant() { assertThat(sdkRuntimeVariantTargetings) .containsExactly( sdkRuntimeVariantTargeting( - ANDROID_T_API_VERSION, /* alternativeSdkVersions= */ ImmutableSet.of())); + ANDROID_U_API_VERSION, /* alternativeSdkVersions= */ ImmutableSet.of())); } @Test @@ -86,66 +86,66 @@ public void noOtherVariantTargetings_generatesOneVariant() { assertThat(sdkRuntimeVariantTargetings) .containsExactly( sdkRuntimeVariantTargeting( - ANDROID_T_API_VERSION, /* alternativeSdkVersions= */ ImmutableSet.of())); + ANDROID_U_API_VERSION, /* alternativeSdkVersions= */ ImmutableSet.of())); } @Test - public void otherVariantTargetingsTargetPreT_generatesOneVariant() { + public void otherVariantTargetingsTargetPreU_generatesOneVariant() { ImmutableSet sdkRuntimeVariantTargetings = new SdkRuntimeVariantGenerator(APP_BUNDLE_WITH_RUNTIME_ENABLED_SDK_DEPS) .generate( ImmutableSet.of( - variantMinSdkTargeting(ANDROID_R_API_VERSION), - variantMinSdkTargeting(ANDROID_S_API_VERSION))); + variantMinSdkTargeting(ANDROID_S_API_VERSION), + variantMinSdkTargeting(ANDROID_T_API_VERSION))); assertThat(sdkRuntimeVariantTargetings) .containsExactly( sdkRuntimeVariantTargeting( - ANDROID_T_API_VERSION, /* alternativeSdkVersions= */ ImmutableSet.of())); + ANDROID_U_API_VERSION, /* alternativeSdkVersions= */ ImmutableSet.of())); } @Test - public void otherVariantTargetingTargetsT_generatesOneVariant() { + public void otherVariantTargetingTargetsU_generatesOneVariant() { ImmutableSet sdkRuntimeVariantTargetings = new SdkRuntimeVariantGenerator(APP_BUNDLE_WITH_RUNTIME_ENABLED_SDK_DEPS) - .generate(ImmutableSet.of(variantMinSdkTargeting(ANDROID_T_API_VERSION))); + .generate(ImmutableSet.of(variantMinSdkTargeting(ANDROID_U_API_VERSION))); assertThat(sdkRuntimeVariantTargetings) .containsExactly( sdkRuntimeVariantTargeting( - ANDROID_T_API_VERSION, /* alternativeSdkVersions= */ ImmutableSet.of())); + ANDROID_U_API_VERSION, /* alternativeSdkVersions= */ ImmutableSet.of())); } @Test - public void otherVariantTargetingsTargetPostT_generatesOneForEachAndT() { + public void otherVariantTargetingsTargetPostU_generatesOneForEachAndT() { ImmutableSet sdkRuntimeVariantTargetings = new SdkRuntimeVariantGenerator(APP_BUNDLE_WITH_RUNTIME_ENABLED_SDK_DEPS) .generate( ImmutableSet.of( - variantMinSdkTargeting(ANDROID_T_API_VERSION + 1), - variantMinSdkTargeting(ANDROID_T_API_VERSION + 2), - variantMinSdkTargeting(ANDROID_T_API_VERSION + 3))); + variantMinSdkTargeting(ANDROID_U_API_VERSION + 1), + variantMinSdkTargeting(ANDROID_U_API_VERSION + 2), + variantMinSdkTargeting(ANDROID_U_API_VERSION + 3))); assertThat(sdkRuntimeVariantTargetings) .containsExactly( - sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION), - sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION + 1), - sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION + 2), - sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION + 3)); + sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION), + sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION + 1), + sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION + 2), + sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION + 3)); } @Test - public void otherVariantTargetingsTargetPreAndPostT_generatesOneForPostTAndT() { + public void otherVariantTargetingsTargetPreAndPostU_generatesOneForPostTAndT() { ImmutableSet sdkRuntimeVariantTargetings = new SdkRuntimeVariantGenerator(APP_BUNDLE_WITH_RUNTIME_ENABLED_SDK_DEPS) .generate( ImmutableSet.of( - variantMinSdkTargeting(ANDROID_S_API_VERSION), - variantMinSdkTargeting(ANDROID_T_API_VERSION + 1))); + variantMinSdkTargeting(ANDROID_T_API_VERSION), + variantMinSdkTargeting(ANDROID_U_API_VERSION + 1))); assertThat(sdkRuntimeVariantTargetings) .containsExactly( - sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION), - sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION + 1)); + sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION), + sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION + 1)); } } diff --git a/src/test/java/com/android/tools/build/bundletool/splitters/SplitApksGeneratorTest.java b/src/test/java/com/android/tools/build/bundletool/splitters/SplitApksGeneratorTest.java index 906b3ce6..3c1e8f66 100644 --- a/src/test/java/com/android/tools/build/bundletool/splitters/SplitApksGeneratorTest.java +++ b/src/test/java/com/android/tools/build/bundletool/splitters/SplitApksGeneratorTest.java @@ -24,7 +24,7 @@ import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_L_API_VERSION; import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_M_API_VERSION; import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_Q_API_VERSION; -import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_T_API_VERSION; +import static com.android.tools.build.bundletool.model.utils.Versions.ANDROID_U_API_VERSION; import static com.android.tools.build.bundletool.testing.ManifestProtoUtils.androidManifest; import static com.android.tools.build.bundletool.testing.ResourcesTableFactory.HDPI; import static com.android.tools.build.bundletool.testing.ResourcesTableFactory.USER_PACKAGE_OFFSET; @@ -610,7 +610,7 @@ public void appBundleHasRuntimeEnabledSdkDeps_generatesSdkRuntimeVariant() { assertThat( moduleSplits.stream().map(ModuleSplit::getVariantTargeting).collect(toImmutableList())) .containsExactly( - lPlusVariantTargeting(), sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION)); + lPlusVariantTargeting(), sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION)); ImmutableMap moduleSplitMap = Maps.uniqueIndex(moduleSplits, ModuleSplit::getVariantTargeting); assertThat( @@ -621,7 +621,7 @@ public void appBundleHasRuntimeEnabledSdkDeps_generatesSdkRuntimeVariant() { .isEmpty(); assertThat( moduleSplitMap - .get(sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION)) + .get(sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION)) .getAndroidManifest() .getUsesSdkLibraryElements()) .hasSize(1); @@ -664,7 +664,7 @@ public void appBundleWithSdkDependencyModule_sdkModuleIncludedInNonSdkRuntimeVar assertThat( moduleSplits.stream().map(ModuleSplit::getVariantTargeting).collect(toImmutableSet())) .containsExactly( - lPlusVariantTargeting(), sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION)); + lPlusVariantTargeting(), sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION)); ImmutableMap> moduleSplitMap = moduleSplits.stream() .collect(toImmutableListMultimap(ModuleSplit::getVariantTargeting, Function.identity())) @@ -675,9 +675,9 @@ public void appBundleWithSdkDependencyModule_sdkModuleIncludedInNonSdkRuntimeVar .map(ModuleSplit::getModuleName) .map(BundleModuleName::getName)) .containsExactly("base", "comTestSdk"); - assertThat(moduleSplitMap.get(sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION))).hasSize(1); + assertThat(moduleSplitMap.get(sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION))).hasSize(1); assertThat( - moduleSplitMap.get(sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION)).stream() + moduleSplitMap.get(sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION)).stream() .map(ModuleSplit::getModuleName) .map(BundleModuleName::getName)) .containsExactly("base"); @@ -753,7 +753,7 @@ public void appBundleWithSdkDependencyModuleAndDensityTargeting_noDensitySplitsF assertThat( moduleSplits.stream().map(ModuleSplit::getVariantTargeting).collect(toImmutableSet())) .containsExactly( - lPlusVariantTargeting(), sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION)); + lPlusVariantTargeting(), sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION)); ImmutableMap> moduleSplitMap = moduleSplits.stream() .collect(toImmutableListMultimap(ModuleSplit::getVariantTargeting, Function.identity())) @@ -780,13 +780,13 @@ public void appBundleWithSdkDependencyModuleAndDensityTargeting_noDensitySplitsF // 1 main split + 7 config splits: 1 per each screen density. assertThat(nonSdkRuntimeVariantBaseModuleSplits).hasSize(8); assertThat( - moduleSplitMap.get(sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION)).stream() + moduleSplitMap.get(sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION)).stream() .map(ModuleSplit::getModuleName) .map(BundleModuleName::getName) .distinct()) .containsExactly("base"); ImmutableSet sdkRuntimeVariantSplits = - moduleSplitMap.get(sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION)).stream() + moduleSplitMap.get(sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION)).stream() .filter(moduleSplit -> moduleSplit.getModuleName().getName().equals("base")) .collect(toImmutableSet()); // 1 main split + 7 config splits: 1 per each screen density. @@ -879,7 +879,7 @@ public void appBundleWithSdkDependencyModuleAndDensityTargeting_noDensitySplitsF assertThat( moduleSplits.stream().map(ModuleSplit::getVariantTargeting).collect(toImmutableSet())) .containsExactly( - lPlusVariantTargeting(), sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION)); + lPlusVariantTargeting(), sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION)); ImmutableMap> moduleSplitMap = moduleSplits.stream() .collect(toImmutableListMultimap(ModuleSplit::getVariantTargeting, Function.identity())) @@ -925,7 +925,7 @@ public void appBundleWithSdkDependencyModuleAndDensityTargeting_noDensitySplitsF // T+ runtime enabled Collection tPlusVariantSplits = - moduleSplitMap.get(sdkRuntimeVariantTargeting(ANDROID_T_API_VERSION)); + moduleSplitMap.get(sdkRuntimeVariantTargeting(ANDROID_U_API_VERSION)); ImmutableSet tPlusSdkModuleSplits = lPlusVariantSplits.stream() .filter(moduleSplit -> moduleSplit.getModuleName().getName().equals("comtestsdk")) diff --git a/src/test/java/com/android/tools/build/bundletool/testing/TargetingUtils.java b/src/test/java/com/android/tools/build/bundletool/testing/TargetingUtils.java index 708edebf..bda9798f 100644 --- a/src/test/java/com/android/tools/build/bundletool/testing/TargetingUtils.java +++ b/src/test/java/com/android/tools/build/bundletool/testing/TargetingUtils.java @@ -16,6 +16,7 @@ package com.android.tools.build.bundletool.testing; +import static com.android.tools.build.bundletool.model.AndroidManifest.SDK_SANDBOX_MIN_VERSION; import static com.android.tools.build.bundletool.model.utils.ProtoUtils.mergeFromProtos; import static com.google.common.base.Predicates.alwaysTrue; import static com.google.common.collect.ImmutableList.toImmutableList; @@ -969,7 +970,7 @@ public static VariantTargeting lPlusVariantTargeting() { } public static VariantTargeting sdkRuntimeVariantTargeting() { - return sdkRuntimeVariantTargeting(Versions.ANDROID_T_API_VERSION); + return sdkRuntimeVariantTargeting(SDK_SANDBOX_MIN_VERSION); } public static VariantTargeting sdkRuntimeVariantTargeting(SdkVersion androidSdkVersion) {