private ImmutableList<ModuleSplit> generateSplitApks(VariantTargeting variantTargeting) { ImmutableSet<String> allModuleNames = modules.stream().map(module -> module.getName().getName()).collect(toImmutableSet()); ImmutableList.Builder<ModuleSplit> splits = ImmutableList.builder(); for (BundleModule module : modules) { ModuleSplitter moduleSplitter = new ModuleSplitter( module, bundleVersion, apkGenerationConfiguration, variantTargeting, allModuleNames, masterResourcesPredicate); splits.addAll(moduleSplitter.splitModule()); } return splits.build(); } }
private ImmutableList<ModuleSplit> runSplitters() { if (targetsOnlyPreL(module)) { throw CommandExecutionException.builder() .withMessage( SplittingPipeline resourcesPipeline = createResourcesSplittingPipeline(); splits.addAll(resourcesPipeline.split(ModuleSplit.forResources(module, variantTargeting))); SplittingPipeline nativePipeline = createNativeLibrariesSplittingPipeline(); splits.addAll(nativePipeline.split(ModuleSplit.forNativeLibraries(module, variantTargeting))); SplittingPipeline assetsPipeline = createAssetsSplittingPipeline(); splits.addAll(assetsPipeline.split(ModuleSplit.forAssets(module, variantTargeting))); SplittingPipeline dexPipeline = createDexSplittingPipeline(); splits.addAll(dexPipeline.split(ModuleSplit.forDex(module, variantTargeting))); new SameTargetingMerger().merge(applyMasterManifestMutators(splits.build()));
/** Common modifications to both the instant and installed splits. */ private ImmutableList<ModuleSplit> splitModuleInternal() { return runSplitters().stream() .map(this::addLPlusApkTargeting) .map(this::writeSplitIdInManifest) .collect(toImmutableList()); }
.build(); ImmutableList<ModuleSplit> splits = createAbiAndDensitySplitter(testModule).splitModule(); assertThat(splits.stream().map(ModuleSplit::getSplitType).distinct().collect(toImmutableSet())) .containsExactly(SplitType.SPLIT);
new BundleModuleBuilder("base").setManifest(androidManifest("com.test.app")).build(); ModuleSplitter moduleSplitter = new ModuleSplitter(bundleModule, BUNDLETOOL_VERSION); assetsSplit1 = moduleSplitter.writeSplitIdInManifest(assetsSplit1); assetsSplit2 = moduleSplitter.writeSplitIdInManifest(assetsSplit2);
private static ModuleSplitter createAbiAndDensitySplitter(BundleModule module) { return new ModuleSplitter( module, BUNDLETOOL_VERSION, withOptimizationDimensions(ImmutableSet.of(ABI, SCREEN_DENSITY)), lPlusVariantTargeting(), ImmutableSet.of(module.getName().getName()), NO_RESOURCES_PINNED_TO_MASTER); }
@Test public void applyMasterManifestMutators_singleVariant() throws Exception { ModuleSplit masterSplit = createModuleSplitBuilder().setVariantTargeting(lPlusVariantTargeting()).build(); ModuleSplit nonMasterSplit = createModuleSplitBuilder() .setMasterSplit(false) .setApkTargeting(apkAbiTargeting(AbiAlias.X86)) .setVariantTargeting(lPlusVariantTargeting()) .addMasterManifestMutator(withExtractNativeLibs(true)) .build(); ImmutableList<ModuleSplit> moduleSplits = ModuleSplitter.applyMasterManifestMutators(ImmutableList.of(masterSplit, nonMasterSplit)); ImmutableMap<Boolean, ModuleSplit> moduleSplitMap = Maps.uniqueIndex(moduleSplits, ModuleSplit::isMasterSplit); assertThat(moduleSplitMap.get(true).getAndroidManifest().getExtractNativeLibsValue().get()) .isTrue(); assertThat(applyManifestMutators(masterSplit, ImmutableList.of(withExtractNativeLibs(true)))) .isEqualTo(moduleSplitMap.get(true)); assertThat(moduleSplitMap.get(false)).isEqualTo(nonMasterSplit); }
public ImmutableList<ModuleSplit> splitModule() { if (apkGenerationConfiguration.isForInstantAppVariants()) { // Returns the list of module splits, ready for use as an instant app. return splitModuleInternal().stream() .map(this::makeInstantManifestChanges) .map(moduleSplit -> moduleSplit.toBuilder().setSplitType(SplitType.INSTANT).build()) .collect(toImmutableList()); } else { return splitModuleInternal().stream() .map(this::removeSplitName) .map(this::addPlaceHolderNativeLibsToBaseModule) .collect(toImmutableList()); } }
@Test public void testSplitsDontHaveBundleConfigFiles() throws Exception { BundleModule bundleModule = new BundleModuleBuilder("testModule") .addFile("assets/dict.dat") .setManifest(androidManifest("com.test.app")) .setNativeConfig(NativeLibraries.getDefaultInstance()) .setAssetsConfig(Assets.getDefaultInstance()) .build(); ImmutableList<ModuleSplit> splits = createAbiAndDensitySplitter(bundleModule).splitModule(); assertThat(splits.stream().map(ModuleSplit::getSplitType).distinct().collect(toImmutableSet())) .containsExactly(SplitType.SPLIT); assertThat( splits .stream() .map(ModuleSplit::getVariantTargeting) .distinct() .collect(toImmutableSet())) .containsExactly(lPlusVariantTargeting()); assertThat(splits).isNotEmpty(); for (ModuleSplit split : splits) { ImmutableSet<ZipPath> pathEntries = split.getEntries().stream().map(ModuleEntry::getPath).collect(toImmutableSet()); assertThat(pathEntries).doesNotContain(ZipPath.create("native.pb")); assertThat(pathEntries).doesNotContain(ZipPath.create("assets.pb")); } }
new BundleModuleBuilder("base").setManifest(androidManifest("com.test.app")).build(); ModuleSplitter moduleSplitter = new ModuleSplitter(bundleModule, BUNDLETOOL_VERSION); assetsSplit1 = moduleSplitter.writeSplitIdInManifest(assetsSplit1); assetsSplit2 = moduleSplitter.writeSplitIdInManifest(assetsSplit2);
private static ModuleSplitter createAbiDensityAndLanguageSplitter(BundleModule module) { return new ModuleSplitter( module, BUNDLETOOL_VERSION, withOptimizationDimensions(ImmutableSet.of(ABI, SCREEN_DENSITY, LANGUAGE)), lPlusVariantTargeting(), ImmutableSet.of(module.getName().getName()), NO_RESOURCES_PINNED_TO_MASTER); }
@Test public void applyMasterManifestMutators_multipleVariants_throws() throws Exception { ModuleSplit masterSplit = createModuleSplitBuilder().setVariantTargeting(lPlusVariantTargeting()).build(); ModuleSplit nonMasterSplit = createModuleSplitBuilder() .setMasterSplit(false) .setApkTargeting(apkAbiTargeting(AbiAlias.X86)) .setVariantTargeting(variantMinSdkTargeting(ANDROID_M_API_VERSION)) .addMasterManifestMutator(withExtractNativeLibs(true)) .build(); Throwable exception = assertThrows( IllegalStateException.class, () -> ModuleSplitter.applyMasterManifestMutators( ImmutableList.of(masterSplit, nonMasterSplit))); assertThat(exception) .hasMessageThat() .contains("Expected same variant targeting across all splits."); }
@Test public void targetsPreLOnlyInManifest_throws() throws Exception { int preL = 20; BundleModule bundleModule = new BundleModuleBuilder("testModule") .setManifest(androidManifest("com.test.app", withMaxSdkVersion(preL))) .build(); CommandExecutionException exception = assertThrows( CommandExecutionException.class, () -> new ModuleSplitter(bundleModule, BUNDLETOOL_VERSION).splitModule()); assertThat(exception) .hasMessageThat() .contains("does not target devices on Android L or above"); }
.build(); ImmutableList<ModuleSplit> splits = createAbiAndDensitySplitter(testModule).splitModule(); assertThat(splits.stream().map(ModuleSplit::getSplitType).distinct().collect(toImmutableSet())) .containsExactly(SplitType.SPLIT);
@Test public void minSdkVersionInOutputTargeting_getsSetToL() throws Exception { BundleModule bundleModule = new BundleModuleBuilder("testModule").setManifest(androidManifest("com.test.app")).build(); ImmutableList<ModuleSplit> moduleSplits = new ModuleSplitter(bundleModule, BUNDLETOOL_VERSION).splitModule(); assertThat(moduleSplits).hasSize(1); ModuleSplit masterSplit = moduleSplits.get(0); assertThat(masterSplit.getSplitType()).isEqualTo(SplitType.SPLIT); assertThat(masterSplit.getVariantTargeting()).isEqualTo(lPlusVariantTargeting()); assertThat(masterSplit.isMasterSplit()).isTrue(); assertThat(masterSplit.getApkTargeting()).isEqualTo(apkMinSdkTargeting(21)); }
createAbiDensityAndLanguageSplitter(testModule).splitModule(); assertThat(splits).hasSize(3); // FR, CZ and the master split. assertThat(splits.stream().map(ModuleSplit::getSplitType).distinct().collect(toImmutableSet()))
new ModuleSplitter( testModule, BUNDLETOOL_VERSION, NO_RESOURCES_PINNED_TO_MASTER); List<ModuleSplit> splits = moduleSplitter.splitModule();
.build(); ImmutableList<ModuleSplit> splits = createAbiAndDensitySplitter(testModule).splitModule(); assertThat(splits.stream().map(ModuleSplit::getSplitType).distinct().collect(toImmutableSet())) .containsExactly(SplitType.SPLIT);
@Test public void addingLibraryPlaceholders_featureModule_noAction() throws Exception { BundleModule baseModule = new BundleModuleBuilder("feature") .addFile("dex/classes.dex") .setManifest(androidManifest("com.test.app")) .build(); ModuleSplitter moduleSplitter = new ModuleSplitter( baseModule, BUNDLETOOL_VERSION, ApkGenerationConfiguration.builder() .setAbisForPlaceholderLibs( ImmutableSet.of(toAbi(AbiAlias.X86), toAbi(AbiAlias.ARM64_V8A))) .build(), lPlusVariantTargeting(), ImmutableSet.of("feature"), NO_RESOURCES_PINNED_TO_MASTER); ImmutableList<ModuleSplit> splits = moduleSplitter.splitModule(); assertThat(splits).hasSize(1); ModuleSplit masterSplit = splits.get(0); assertThat(masterSplit.isMasterSplit()).isTrue(); assertThat(extractPaths(masterSplit.getEntries())).containsExactly("dex/classes.dex"); }
.build(); List<ModuleSplit> splits = createAbiDensityAndLanguageSplitter(bundleModule).splitModule(); assertThat(splits.stream().map(ModuleSplit::getSplitType).distinct().collect(toImmutableSet())) .containsExactly(SplitType.SPLIT);