private SplittingPipeline createResourcesSplittingPipeline( ImmutableSet<OptimizationDimension> shardingDimensions) { return new SplittingPipeline( shardingDimensions.contains(OptimizationDimension.SCREEN_DENSITY) ? ImmutableList.of( new ScreenDensityResourcesSplitter( bundleVersion, /* pinResourceToMaster= */ Predicates.alwaysFalse())) : ImmutableList.of()); }
ResourceTable optimizedTable = filterResourceTableForDensity(resourceTable.get(), density); .setScreenDensityTargeting( ScreenDensityTargeting.newBuilder() .addValue(toScreenDensity(density)) .addAllAlternatives( allBut(densityBuckets, density).stream() .map(ScreenDensityResourcesSplitter::toScreenDensity) .collect(toImmutableList()))) ModuleSplit defaultResourcesSplit = getDefaultResourcesSplit(split, splitsBuilder.build()); return splitsBuilder.add(defaultResourcesSplit).build();
!bundleVersion.isOlderThan(Version.of("0.4.0")) || configValue.getConfig().getDensity() != DEFAULT_DENSITY_VALUE) .collect(groupingBy(configValue -> clearDensity(configValue.getConfig()))); ImmutableList.copyOf(configValuesByConfiguration.values()); ImmutableList<ConfigValue> valuesToKeep = pickBestDensityForEachGroup(densityGroups, targetDensity); return initialEntry.toBuilder().clearConfigValue().addAllConfigValue(valuesToKeep).build();
/** Creates resources split with no extra targeting with all other unclaimed resource entries. */ private ModuleSplit getDefaultResourcesSplit( ModuleSplit inputSplit, ImmutableCollection<ModuleSplit> densitySplits) { ResourceTable defaultSplitTable = getResourceTableForDefaultSplit(inputSplit, getClaimedConfigs(densitySplits)); return inputSplit .toBuilder() .setEntries(ModuleSplit.filterResourceEntries(inputSplit.getEntries(), defaultSplitTable)) .setResourceTable(defaultSplitTable) .build(); }
resource -> resource.getResourceId().getFullResourceId() == 0x7f010000; ScreenDensityResourcesSplitter splitter = new ScreenDensityResourcesSplitter( BundleToolVersion.getCurrentVersion(), masterResourcesPredicate); splitter.split(ModuleSplit.forResources(testModule));
DensityAlias.XXXHDPI); ImmutableCollection<ModuleSplit> densitySplits = splitter.split(ModuleSplit.forResources(testModule)); for (ModuleSplit resourceSplit : densitySplits) { assertThat(resourceSplit.getResourceTable().isPresent()).isTrue();
/** For each density group, it picks the best match for a given desired densityAlias. */ private ImmutableList<ConfigValue> pickBestDensityForEachGroup( ImmutableList<List<ConfigValue>> densityGroups, DensityAlias densityAlias) { return densityGroups.stream() .flatMap( group -> new ScreenDensitySelector() .selectAllMatchingConfigValues( ImmutableList.copyOf(group), densityAlias, allBut(densityBuckets, densityAlias)) .stream()) .collect(toImmutableList()); }
private ResourceTable filterResourceTableForDensity(ResourceTable input, DensityAlias density) { return ResourcesUtils.filterResourceTable( input, // Put mipmaps into the master split. /* removeEntryPredicate= */ pinResourceToMaster.or( resourceTableEntry -> resourceTableEntry.getType().getName().equals(MIPMAP_TYPE)), /* configValuesFilterFn= */ entry -> filterEntryForDensity(entry, density)); }
new ScreenDensityResourcesSplitter(Version.of("0.3.3"), NO_RESOURCES_PINNED_TO_MASTER); ImmutableCollection<ModuleSplit> splits = splitter.split(ModuleSplit.forResources(module));
@Test public void noResourceTable_noResourceSplits() throws Exception { BundleModule testModule = new BundleModuleBuilder("testModule") .addFile("lib/x86/liba.so") .setManifest(androidManifest("com.test.app")) .build(); assertThat(splitter.split(ModuleSplit.forResources(testModule))) .containsExactly(ModuleSplit.forResources(testModule)); }
new ScreenDensityResourcesSplitter(Version.of("0.3.3"), NO_RESOURCES_PINNED_TO_MASTER); ImmutableCollection<ModuleSplit> splits = splitter.split(ModuleSplit.forResources(module));
DensityAlias.XXXHDPI); ImmutableCollection<ModuleSplit> densitySplits = splitter.split(ModuleSplit.forResources(testModule)); assertThat(densitySplits).hasSize(DEFAULT_DENSITY_BUCKETS.size() + 1); assertThat(
private SplittingPipeline createResourcesSplittingPipeline() { ImmutableList.Builder<ModuleSplitSplitter> resourceSplitters = ImmutableList.builder(); if (apkGenerationConfiguration .getOptimizationDimensions() .contains(OptimizationDimension.SCREEN_DENSITY)) { resourceSplitters.add(new ScreenDensityResourcesSplitter(bundleVersion, pinResourceToMaster)); } if (apkGenerationConfiguration .getOptimizationDimensions() .contains(OptimizationDimension.LANGUAGE)) { resourceSplitters.add(new LanguageResourcesSplitter(pinResourceToMaster)); } return new SplittingPipeline(resourceSplitters.build()); }
new ScreenDensityResourcesSplitter( ImmutableSet.of(DensityAlias.XXHDPI, DensityAlias.XXXHDPI), BundleToolVersion.getCurrentVersion(), NO_RESOURCES_PINNED_TO_MASTER); ImmutableCollection<ModuleSplit> densitySplits = splitter.split(ModuleSplit.forResources(module));
splitter.split(ModuleSplit.forResources(testModule));
@Test public void manifestMutatorToRequireSplits_notRegistered_whenNoDensityResources() throws Exception { BundleModule testModule = new BundleModuleBuilder("testModule") .addFile("res/drawable/test.jpg") .setResourceTable( resourceTable( pkg( USER_PACKAGE_OFFSET, "com.test.app", type( 0x01, "drawable", entry( 0x01, "test", fileReference( "res/drawable/test.jpg", Configuration.getDefaultInstance())))))) .setManifest(androidManifest("com.test.app")) .build(); ModuleSplit resourcesModule = ModuleSplit.forResources(testModule); ImmutableCollection<ModuleSplit> splits = splitter.split(resourcesModule); assertThat(splits).hasSize(1); assertThat(splits.asList().get(0).getMasterManifestMutators()).isEmpty(); }
@Test public void preservesSourcePool() throws Exception { StringPool sourcePool = StringPool.newBuilder().setData(ByteString.copyFrom(new byte[] {'x'})).build(); ResourceTable table = new ResourceTableBuilder() .addPackage("com.test.app") .addDrawableResourceForMultipleDensities( "image", ImmutableMap.of(MDPI_VALUE, "res/drawable-mdpi/image.jpg")) .build() .toBuilder() .setSourcePool(sourcePool) .build(); BundleModule testModule = new BundleModuleBuilder("testModule") .addFile("res/drawable-mdpi/test.jpg") .setResourceTable(table) .setManifest(androidManifest("com.test.app")) .build(); ImmutableCollection<ModuleSplit> densitySplits = splitter.split(ModuleSplit.forResources(testModule)); assertThat(densitySplits).hasSize(DEFAULT_DENSITY_BUCKETS.size() + 1); for (ModuleSplit densitySplit : densitySplits) { assertThat(densitySplit.getResourceTable()).isPresent(); assertThat(densitySplit.getResourceTable().get().getSourcePool()).isEqualTo(sourcePool); } }
@Test public void nonDefaultDensityResourceWithoutAlternatives() throws Exception { ResourceTable table = resourceTable( pkg( USER_PACKAGE_OFFSET, "com.test.app", type( 0x01, "drawable", entry(0x01, "image", fileReference("res/drawable-hdpi/image.jpg", HDPI))))); BundleModule module = new BundleModuleBuilder("base") .addFile("res/drawable-hdpi/image.jpg") .setResourceTable(table) .setManifest(androidManifest("com.test.app")) .build(); ImmutableCollection<ModuleSplit> splits = splitter.split(ModuleSplit.forResources(module)); // No config split because the resource has no alternatives so ends up in the master split. assertThat(splits).hasSize(1); ModuleSplit masterSplit = findModuleSplitWithDefaultTargeting(splits); assertThat(masterSplit.getResourceTable().get()) .containsResource("com.test.app:drawable/image") .onlyWithConfigs(HDPI); assertThat(masterSplit.findEntry("res/drawable-hdpi/image.jpg")).isPresent(); }
@Test public void noDensityResources_noDensitySplits() throws Exception { BundleModule testModule = new BundleModuleBuilder("testModule") .addFile("res/drawable/test.jpg") .setResourceTable( resourceTable( pkg( USER_PACKAGE_OFFSET, "com.test.app", type( 0x01, "drawable", entry( 0x01, "test", fileReference( "res/drawable/test.jpg", Configuration.getDefaultInstance())))))) .setManifest(androidManifest("com.test.app")) .build(); ModuleSplit resourcesModule = ModuleSplit.forResources(testModule); ImmutableCollection<ModuleSplit> splits = splitter.split(resourcesModule); assertThat(splits).hasSize(1); ModuleSplit baseSplit = splits.iterator().next(); assertThat(baseSplit.getResourceTable().get()).containsResource("com.test.app:drawable/test"); assertThat(baseSplit.findEntry("res/drawable/test.jpg")).isPresent(); }
@Test public void defaultDensityResourceWithoutAlternatives() throws Exception { ResourceTable table = resourceTable( pkg( USER_PACKAGE_OFFSET, "com.test.app", type( 0x01, "drawable", entry( 0x01, "image", fileReference( "res/drawable/image.jpg", Configuration.getDefaultInstance()))))); BundleModule module = new BundleModuleBuilder("base") .addFile("res/drawable/image.jpg") .setResourceTable(table) .setManifest(androidManifest("com.test.app")) .build(); ImmutableCollection<ModuleSplit> splits = splitter.split(ModuleSplit.forResources(module)); // No config split because the resource has no alternatives so ends up in the master split. assertThat(splits).hasSize(1); ModuleSplit masterSplit = findModuleSplitWithDefaultTargeting(splits); assertThat(masterSplit.getResourceTable().get()) .containsResource("com.test.app:drawable/image") .onlyWithConfigs(Configuration.getDefaultInstance()); assertThat(masterSplit.findEntry("res/drawable/image.jpg")).isPresent(); }