use of com.android.bundle.Commands.ApkDescription in project bundletool by google.
the class ApkSetWriter method zip.
/**
* Creates ApkSet writer which stores all splits as ZIP archive.
*/
static ApkSetWriter zip(Path tempDirectory, Path outputFile) {
return new ApkSetWriter() {
@Override
public Path getSplitsDirectory() {
return tempDirectory;
}
@Override
public void writeApkSet(BuildApksResult toc) throws IOException {
Stream<ApkDescription> apks = toc.getVariantList().stream().flatMap(variant -> variant.getApkSetList().stream()).flatMap(apkSet -> apkSet.getApkDescriptionList().stream());
Stream<ApkDescription> assets = toc.getAssetSliceSetList().stream().flatMap(assetSliceSet -> assetSliceSet.getApkDescriptionList().stream());
ImmutableSet<String> apkRelativePaths = Stream.concat(apks, assets).map(ApkDescription::getPath).sorted().collect(toImmutableSet());
zipApkSet(apkRelativePaths, toc.toByteArray());
}
@Override
public void writeApkSet(BuildSdkApksResult toc) throws IOException {
Stream<ApkDescription> apks = toc.getVariantList().stream().flatMap(variant -> variant.getApkSetList().stream()).flatMap(apkSet -> apkSet.getApkDescriptionList().stream());
ImmutableSet<String> apkRelativePaths = apks.map(ApkDescription::getPath).sorted().collect(toImmutableSet());
zipApkSet(apkRelativePaths, toc.toByteArray());
}
private void zipApkSet(ImmutableSet<String> apkRelativePaths, byte[] tocBytes) throws IOException {
try (ZipArchive zipArchive = new ZipArchive(outputFile)) {
zipArchive.add(new BytesSource(tocBytes, TABLE_OF_CONTENTS_FILE, Deflater.NO_COMPRESSION));
for (String relativePath : apkRelativePaths) {
zipArchive.add(new LargeFileSource(getSplitsDirectory().resolve(relativePath), /* tmpStorage= */
null, relativePath, Deflater.NO_COMPRESSION));
}
}
}
};
}
use of com.android.bundle.Commands.ApkDescription in project bundletool by google.
the class BuildSdkApksManagerTest method sdkManifestMutation_patchVersionNotSet_defaultPatchVersionAdded.
@Test
public void sdkManifestMutation_patchVersionNotSet_defaultPatchVersionAdded() throws Exception {
SdkBundle sdkBundle = new SdkBundleBuilder().setModule(new BundleModuleBuilder("base").setManifest(androidManifest(PACKAGE_NAME, withSdkLibraryElement("20"))).build()).build();
execute(sdkBundle);
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.getMetadataValue(SDK_PATCH_VERSION_ATTRIBUTE_NAME)).hasValue(DEFAULT_SDK_PATCH_VERSION);
}
use of com.android.bundle.Commands.ApkDescription in project bundletool by google.
the class ApkSerializerManager method serializeApks.
@VisibleForTesting
ImmutableList<Variant> serializeApks(Path outputDirectory, GeneratedApks generatedApks, Optional<DeviceSpec> deviceSpec) {
validateInput(generatedApks, apkBuildMode);
// Running with system APK mode generates a fused APK and additional unmatched language splits.
// To avoid filtering of unmatched language splits we skip device filtering for system mode.
Predicate<ModuleSplit> deviceFilter = deviceSpec.isPresent() && !apkBuildMode.equals(SYSTEM) ? new ApkMatcher(addDefaultDeviceTierIfNecessary(deviceSpec.get()))::matchesModuleSplitByTargeting : alwaysTrue();
ImmutableListMultimap<VariantKey, ModuleSplit> splitsByVariant = generatedApks.getAllApksGroupedByOrderedVariants();
// Assign the variant numbers to each variant present.
AtomicInteger variantNumberCounter = new AtomicInteger(firstVariantNumber);
ImmutableMap<VariantKey, Integer> variantNumberByVariantKey = splitsByVariant.keySet().stream().collect(toImmutableMap(identity(), unused -> variantNumberCounter.getAndIncrement()));
// 1. Remove APKs not matching the device spec.
// 2. Modify the APKs based on the ApkModifier.
// 3. Serialize all APKs in parallel.
// Modifies the APK using APK modifier, then returns a map by extracting the variant
// of APK first and later clearing out its variant targeting.
ImmutableListMultimap<VariantKey, ModuleSplit> finalSplitsByVariant = splitsByVariant.entries().stream().filter(keyModuleSplitEntry -> deviceFilter.test(keyModuleSplitEntry.getValue())).collect(groupingBySortedKeys(Entry::getKey, entry -> clearVariantTargeting(modifyApk(entry.getValue(), variantNumberByVariantKey.get(entry.getKey())))));
// After variant targeting of APKs are cleared, there might be duplicate APKs
// which are removed and the distinct APKs are then serialized in parallel.
ImmutableBiMap<ZipPath, ModuleSplit> splitsByRelativePath = finalSplitsByVariant.values().stream().distinct().collect(toImmutableBiMap(apkPathManager::getApkPath, identity()));
ImmutableMap<ZipPath, ApkDescription> apkDescriptionsByRelativePath = apkSerializer.serialize(outputDirectory, splitsByRelativePath);
// Build the result proto.
ImmutableList.Builder<Variant> variants = ImmutableList.builder();
for (VariantKey variantKey : finalSplitsByVariant.keySet()) {
Variant.Builder variant = Variant.newBuilder().setVariantNumber(variantNumberByVariantKey.get(variantKey)).setTargeting(variantKey.getVariantTargeting());
Multimap<BundleModuleName, ModuleSplit> splitsByModuleName = finalSplitsByVariant.get(variantKey).stream().collect(groupingBySortedKeys(ModuleSplit::getModuleName));
for (BundleModuleName moduleName : splitsByModuleName.keySet()) {
variant.addApkSet(ApkSet.newBuilder().setModuleMetadata(bundle.getModule(moduleName).getModuleMetadata()).addAllApkDescription(splitsByModuleName.get(moduleName).stream().map(split -> splitsByRelativePath.inverse().get(split)).map(apkDescriptionsByRelativePath::get).collect(toImmutableList())));
}
variants.add(variant.build());
}
return variants.build();
}
use of com.android.bundle.Commands.ApkDescription in project bundletool by google.
the class ApksArchiveHelpers method createApksDirectory.
public static Path createApksDirectory(BuildApksResult result, Path location) throws Exception {
ImmutableList<ApkDescription> apkDescriptions = apkDescriptionStream(result).collect(toImmutableList());
for (ApkDescription apkDescription : apkDescriptions) {
Path apkPath = location.resolve(apkDescription.getPath());
Files.createDirectories(apkPath.getParent());
Files.write(apkPath, DUMMY_BYTES);
}
Files.write(location.resolve("toc.pb"), result.toByteArray());
return location;
}
use of com.android.bundle.Commands.ApkDescription in project bundletool by google.
the class BuildApksManagerTest method buildApksCommand_standalone_noTextureTargeting.
@Test
public void buildApksCommand_standalone_noTextureTargeting() throws Exception {
AppBundle appBundle = new AppBundleBuilder().addModule("base", builder -> builder.setManifest(androidManifest("com.test.app")).setResourceTable(resourceTableWithTestLabel("Test feature"))).addModule("feature_tcf_assets", builder -> builder.addFile("assets/textures#tcf_atc/texture.dat").addFile("assets/textures#tcf_etc1/texture.dat").setAssetsConfig(assets(targetedAssetsDirectory("assets/textures#tcf_atc", assetsDirectoryTargeting(textureCompressionTargeting(ATC))), targetedAssetsDirectory("assets/textures#tcf_etc1", assetsDirectoryTargeting(textureCompressionTargeting(ETC1_RGB8))))).setManifest(androidManifestForFeature("com.test.app", withTitle("@string/test_label", TEST_LABEL_RESOURCE_ID)))).build();
TestComponent.useTestModule(this, createTestModuleBuilder().withAppBundle(appBundle).withOutputPath(outputFilePath).withOptimizationDimensions(TEXTURE_COMPRESSION_FORMAT).build());
buildApksManager.execute();
ZipFile apkSetFile = openZipFile(outputFilePath.toFile());
BuildApksResult result = extractTocFromApkSetFile(apkSetFile, outputDir);
assertThat(standaloneApkVariants(result)).hasSize(1);
assertThat(apkDescriptions(standaloneApkVariants(result))).hasSize(1);
ApkDescription shard = apkDescriptions(standaloneApkVariants(result)).get(0);
assertThat(apkSetFile).hasFile(shard.getPath());
try (ZipFile shardZip = new ZipFile(extractFromApkSetFile(apkSetFile, shard.getPath(), outputDir))) {
// Even if we used targeted folders, they are all included because we did not activate
// texture targeting optimization.
assertThat(shardZip).hasFile("assets/textures#tcf_atc/texture.dat");
assertThat(shardZip).hasFile("assets/textures#tcf_etc1/texture.dat");
// Suffix stripping was NOT applied (because again we did not even activate texture targeting
// optimization).
assertThat(shardZip).doesNotHaveFile("assets/textures/texture.dat");
}
}
Aggregations