Skip to content

Commit

Permalink
Prepare for release 1.11.1.
Browse files Browse the repository at this point in the history
  • Loading branch information
Iurii Makhno committed Sep 3, 2022
1 parent 1082065 commit 0583e1f
Show file tree
Hide file tree
Showing 115 changed files with 3,689 additions and 365 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.11.0](https://github.com/google/bundletool/releases)
Latest release: [1.11.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.11.0
release_version = 1.11.1
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.android.tools.build.bundletool.androidtools;

import com.android.tools.build.bundletool.androidtools.CommandExecutor.CommandOptions;
import com.android.tools.build.bundletool.model.utils.OsPlatform;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
Expand Down Expand Up @@ -88,12 +89,14 @@ ImmutableList<String> installMultiPackage(
.add("--staged-ready-timeout")
.add(String.format("%d", timeout.get().toMillis()));
}
String splitCharacter = (OsPlatform.getCurrentPlatform() == OsPlatform.WINDOWS) ? ";" : ":";
// Splits of a single package must be installed together.
apkToInstallByPackage
.keySet()
.forEach(
packageName ->
commandBuilder.add(String.join(":", apkToInstallByPackage.get(packageName))));
commandBuilder.add(
String.join(splitCharacter, apkToInstallByPackage.get(packageName))));

logger.info(String.format("Executing: %s", String.join(" ", commandBuilder.build())));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

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

import static com.android.tools.build.bundletool.archive.ArchivedResourcesUtils.ARCHIVED_ICON_DRAWABLE_NAME;
import static com.android.tools.build.bundletool.archive.ArchivedResourcesUtils.ARCHIVED_ROUND_ICON_DRAWABLE_NAME;
import static com.android.tools.build.bundletool.model.AndroidManifest.ALLOW_BACKUP_RESOURCE_ID;
import static com.android.tools.build.bundletool.model.AndroidManifest.ANDROID_NAMESPACE_URI;
import static com.android.tools.build.bundletool.model.AndroidManifest.BACKUP_AGENT_RESOURCE_ID;
Expand All @@ -36,6 +38,7 @@
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;

/** Utility methods for creation of archived manifest. */
public final class ArchivedAndroidManifestUtils {
Expand Down Expand Up @@ -67,6 +70,7 @@ public final class ArchivedAndroidManifestUtils {
AndroidManifest.HAS_FRAGILE_USER_DATA_RESOURCE_ID,
AndroidManifest.IS_GAME_RESOURCE_ID,
AndroidManifest.ICON_RESOURCE_ID,
AndroidManifest.ROUND_ICON_RESOURCE_ID,
AndroidManifest.BANNER_RESOURCE_ID,
AndroidManifest.LABEL_RESOURCE_ID,
AndroidManifest.FULL_BACKUP_ONLY_RESOURCE_ID,
Expand Down Expand Up @@ -133,6 +137,24 @@ private static XmlProtoNode createMinimalManifestTag() {
.build());
}

public static AndroidManifest updateArchivedIcons(
AndroidManifest manifest, ImmutableMap<String, Integer> resourceNameToIdMap) {
ManifestEditor archivedManifestEditor = manifest.toEditor();

if (manifest.getIconAttribute().isPresent()
&& resourceNameToIdMap.containsKey(ARCHIVED_ICON_DRAWABLE_NAME)) {
archivedManifestEditor.setIcon(resourceNameToIdMap.get(ARCHIVED_ICON_DRAWABLE_NAME));
}

if (manifest.getRoundIconAttribute().isPresent()
&& resourceNameToIdMap.containsKey(ARCHIVED_ROUND_ICON_DRAWABLE_NAME)) {
archivedManifestEditor.setRoundIcon(
resourceNameToIdMap.get(ARCHIVED_ROUND_ICON_DRAWABLE_NAME));
}

return archivedManifestEditor.save();
}

private static Activity createReactivateActivity(AndroidManifest manifest) {
IntentFilter.Builder intentFilterBuilder =
IntentFilter.builder().addActionName(MAIN_ACTION_NAME);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,25 @@
import static com.google.common.base.Preconditions.checkNotNull;

import com.android.aapt.Resources.ResourceTable;
import com.android.tools.build.bundletool.io.TempDirectory;
import com.android.tools.build.bundletool.commands.BuildApksModule.UpdateIconInArchiveMode;
import com.android.tools.build.bundletool.model.AndroidManifest;
import com.android.tools.build.bundletool.model.AppBundle;
import com.android.tools.build.bundletool.model.BundleModule;
import com.android.tools.build.bundletool.model.ModuleSplit;
import com.android.tools.build.bundletool.model.ResourceId;
import com.android.tools.build.bundletool.model.ResourceInjector;
import com.android.tools.build.bundletool.model.ResourceTableEntry;
import com.android.tools.build.bundletool.model.ZipPath;
import com.android.tools.build.bundletool.model.exceptions.InvalidCommandException;
import com.android.tools.build.bundletool.model.utils.ResourcesUtils;
import com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoAttribute;
import com.android.tools.build.bundletool.model.version.BundleToolVersion;
import com.android.tools.build.bundletool.model.version.Version;
import com.android.tools.build.bundletool.splitters.ResourceAnalyzer;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.ByteSource;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Optional;
import javax.inject.Inject;

Expand All @@ -48,17 +48,11 @@
* resources and two custom actions to clear app cache and to wake up an app.
*/
public final class ArchivedApksGenerator {
public static final String APP_STORE_PACKAGE_NAME_RESOURCE_NAME =
"reactivation_app_store_package_name";
public static final String PLAY_STORE_PACKAGE_NAME = "com.android.vending";

private static final String ARCHIVED_CLASSES_DEX_PATH = "dex/classes.dex";

private final TempDirectory globalTempDir;
private final boolean updateIconInArchiveMode;

@Inject
ArchivedApksGenerator(TempDirectory globalTempDir) {
this.globalTempDir = globalTempDir;
ArchivedApksGenerator(@UpdateIconInArchiveMode boolean updateIconInArchiveMode) {
this.updateIconInArchiveMode = updateIconInArchiveMode;
}

public ModuleSplit generateArchivedApk(
Expand All @@ -70,12 +64,42 @@ public ModuleSplit generateArchivedApk(
AndroidManifest archivedManifest =
ArchivedAndroidManifestUtils.createArchivedManifest(baseModule.getAndroidManifest());
ResourceTable archivedResourceTable =
getArchivedResourceTable(
appBundle, baseModule, archivedManifest, customAppStorePackageName);
Path archivedClassesDexFile = getArchivedClassesDexFile();
getArchivedResourceTable(appBundle, baseModule, archivedManifest);

Optional<XmlProtoAttribute> iconAttribute = archivedManifest.getIconAttribute();
Optional<XmlProtoAttribute> roundIconAttribute = archivedManifest.getRoundIconAttribute();
ResourceInjector resourceInjector =
new ResourceInjector(archivedResourceTable.toBuilder(), appBundle.getPackageName());

ImmutableMap<ZipPath, ByteSource> additionalResourcesByByteSource = ImmutableMap.of();
if (updateIconInArchiveMode) {
ImmutableMap<String, Integer> extraResourceNameToIdMap =
ArchivedResourcesUtils.injectExtraResources(
resourceInjector, customAppStorePackageName, iconAttribute, roundIconAttribute);

additionalResourcesByByteSource =
ArchivedResourcesUtils.buildAdditionalResourcesByByteSourceMap(
extraResourceNameToIdMap.get(ArchivedResourcesUtils.CLOUD_SYMBOL_DRAWABLE_NAME),
extraResourceNameToIdMap.get(ArchivedResourcesUtils.OPACITY_LAYER_DRAWABLE_NAME),
iconAttribute,
roundIconAttribute);

archivedManifest =
ArchivedAndroidManifestUtils.updateArchivedIcons(
archivedManifest, extraResourceNameToIdMap);
} else {
resourceInjector.addStringResource(
ArchivedResourcesUtils.APP_STORE_PACKAGE_NAME_RESOURCE_NAME,
ArchivedResourcesUtils.getAppStorePackageName(customAppStorePackageName));
additionalResourcesByByteSource =
ImmutableMap.of(
BundleModule.DEX_DIRECTORY.resolve("classes.dex"),
ArchivedResourcesUtils.getResourceByteSource(
ArchivedResourcesUtils.ARCHIVED_CLASSES_DEX_PATH));
}

return ModuleSplit.forArchive(
baseModule, archivedManifest, archivedResourceTable, archivedClassesDexFile);
baseModule, archivedManifest, resourceInjector.build(), additionalResourcesByByteSource);
}

private void validateRequest(AppBundle appBundle) {
Expand Down Expand Up @@ -110,15 +134,13 @@ private void validateRequest(AppBundle appBundle) {
}

private ResourceTable getArchivedResourceTable(
AppBundle appBundle,
BundleModule bundleModule,
AndroidManifest archivedManifest,
Optional<String> customAppStorePackageName)
AppBundle appBundle, BundleModule bundleModule, AndroidManifest archivedManifest)
throws IOException {
ResourceTable.Builder archivedResourceTable = ResourceTable.newBuilder();
if (bundleModule.getResourceTable().isPresent()) {
ImmutableSet<ResourceId> referredResources =
new ResourceAnalyzer(appBundle).findAllAppResourcesReachableFromManifest(archivedManifest);
ImmutableSet<ResourceId> referredResources =
new ResourceAnalyzer(appBundle)
.findAllAppResourcesReachableFromManifest(archivedManifest);
archivedResourceTable =
ResourcesUtils.filterResourceTable(
bundleModule.getResourceTable().get(),
Expand All @@ -127,26 +149,6 @@ private ResourceTable getArchivedResourceTable(
/* configValuesFilterFn= */ ResourceTableEntry::getEntry)
.toBuilder();
}
ResourceInjector resourceInjector =
new ResourceInjector(archivedResourceTable, appBundle.getPackageName());
resourceInjector.addStringResource(
APP_STORE_PACKAGE_NAME_RESOURCE_NAME, getAppStorePackageName(customAppStorePackageName));
return resourceInjector.build();
}

private static String getAppStorePackageName(Optional<String> customAppStorePackageName) {
return customAppStorePackageName.orElse(PLAY_STORE_PACKAGE_NAME);
}

private Path getArchivedClassesDexFile() throws IOException {
Path archivedDexFilePath = Files.createTempFile(globalTempDir.getPath(), "classes", ".dex");
try (InputStream inputStream = readArchivedClassesDexFile()) {
Files.copy(inputStream, archivedDexFilePath, StandardCopyOption.REPLACE_EXISTING);
}
return archivedDexFilePath;
}

private static InputStream readArchivedClassesDexFile() {
return ArchivedApksGenerator.class.getResourceAsStream(ARCHIVED_CLASSES_DEX_PATH);
return archivedResourceTable.build();
}
}
Loading

0 comments on commit 0583e1f

Please sign in to comment.