moduleSplit.getNativeConfig().get().getDirectoryList();
private static NativeLibraries filterNativeTargeting( NativeLibraries nativeLibraries, ImmutableMultimap<ZipPath, ModuleEntry> preservedEntriesByAbiDir) { ImmutableSet<String> preservedAbiDirs = preservedEntriesByAbiDir.keySet().stream().map(ZipPath::toString).collect(toImmutableSet()); return nativeLibraries .toBuilder() .clearDirectory() .addAllDirectory( nativeLibraries.getDirectoryList().stream() .filter(targetedDirectory -> preservedAbiDirs.contains(targetedDirectory.getPath())) .collect(toImmutableList())) .build(); } }
private static void validateTargeting(BundleModule module, NativeLibraries nativeLibraries) { for (TargetedNativeDirectory targetedDirectory : nativeLibraries.getDirectoryList()) { ZipPath path = ZipPath.create(targetedDirectory.getPath()); NativeDirectoryTargeting targeting = targetedDirectory.getTargeting(); .map(libFile -> libFile.getPath().subpath(0, 2).toString()) .collect(toImmutableSet()), nativeLibraries.getDirectoryList().stream() .map(TargetedNativeDirectory::getPath) .collect(toImmutableSet()));
ZipPath.create("moduleX/assets.pb"), Assets.getDefaultInstance()) .addFileWithProtoContent( ZipPath.create("moduleX/native.pb"), NativeLibraries.getDefaultInstance()) .addFileWithProtoContent( ZipPath.create("moduleX/resources.pb"), ResourceTable.getDefaultInstance())
moduleSplit.getNativeConfig().get().getDirectoryList();
@Test public void nativeLibrariesPresent_abiTargetingIsPresent() throws Exception { Path moduleWithAbi = new ZipBuilder() .addFileWithContent(ZipPath.create("lib/x86/libfast.so"), "native data".getBytes(UTF_8)) .addFileWithContent( ZipPath.create("lib/x86/libfaster.so"), "native data".getBytes(UTF_8)) .addFileWithProtoContent( ZipPath.create("manifest/AndroidManifest.xml"), androidManifest(PKG_NAME)) .writeTo(tmpDir.resolve("base.zip")); BuildBundleCommand.builder() .setOutputPath(bundlePath) .setModulesPaths(ImmutableList.of(moduleWithAbi)) .build() .execute(); ZipFile bundle = new ZipFile(bundlePath.toFile()); assertThat(bundle).hasFile("base/native.pb"); NativeLibraries actualTargeting = NativeLibraries.parseFrom(bundle.getInputStream(new ZipEntry("base/native.pb"))); NativeLibraries expectedTargeting = NativeLibraries.newBuilder() .addDirectory( TargetedNativeDirectory.newBuilder() .setPath("lib/x86") .setTargeting( NativeDirectoryTargeting.newBuilder() .setAbi(Abi.newBuilder().setAlias(X86)))) .build(); Truth.assertThat(actualTargeting).isEqualTo(expectedTargeting); }
@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")); } }
/** * Returns a set of ABIs that this App Bundle targets. * * <p>Note that the each module of the App Bundle must target the same set of ABIs or have no * native code. * * <p>Returns empty set if the App Bundle has no native code at all. */ public ImmutableSet<Abi> getTargetedAbis() { return getFeatureModules().values().stream() .map(BundleModule::getNativeConfig) .flatMap( nativeConfig -> { if (nativeConfig.isPresent()) { return nativeConfig.get().getDirectoryList().stream() .map(TargetedNativeDirectory::getTargeting) .map(NativeDirectoryTargeting::getAbi); } else { return Stream.empty(); } }) .distinct() .collect(toImmutableSet()); }
@Test public void differentNativeConfig_ok() throws Exception { String filePath = "native.pb"; byte[] fileContentA = NativeLibraries.getDefaultInstance().toByteArray(); byte[] fileContentB = NativeLibraries.newBuilder() .addDirectory(TargetedNativeDirectory.getDefaultInstance()) .build() .toByteArray(); assertThat(fileContentA).isNotEqualTo(fileContentB); BundleModule moduleA = new BundleModuleBuilder("a") .addFile(filePath, fileContentA) .setManifest(androidManifest("com.test.app")) .build(); BundleModule moduleB = new BundleModuleBuilder("b") .addFile(filePath, fileContentB) .setManifest(androidManifest("com.test.app")) .build(); new EntryClashValidator().validateAllModules(ImmutableList.of(moduleA, moduleB)); }
/** * Processes given native library directories, generating targeting based on their names. * * @param libDirectories Names of directories under lib/, including the "lib/" prefix. * @return Targeting for the given native libraries directories. */ public NativeLibraries generateTargetingForNativeLibraries(Collection<String> libDirectories) { NativeLibraries.Builder nativeLibraries = NativeLibraries.newBuilder(); for (String directory : libDirectories) { checkRootDirectoryName(LIB_DIR, directory); // Split the directory under lib/ into tokens. String abiName = directory.substring(LIB_DIR.length()); Abi abi = checkAbiName(abiName, directory); nativeLibraries.addDirectory( TargetedNativeDirectory.newBuilder() .setPath(directory) .setTargeting(NativeDirectoryTargeting.newBuilder().setAbi(abi)) .build()); } return nativeLibraries.build(); }
@Test public void specialFiles_areNotStoredAsEntries() throws Exception { BundleModule bundleModule = BundleModule.builder() .setName(BundleModuleName.create("testModule")) .setBundleConfig(DEFAULT_BUNDLE_CONFIG) .addEntry( InMemoryModuleEntry.ofFile( "manifest/AndroidManifest.xml", androidManifest("com.test.app").toByteArray())) .addEntry( InMemoryModuleEntry.ofFile("assets.pb", Assets.getDefaultInstance().toByteArray())) .addEntry( InMemoryModuleEntry.ofFile( "native.pb", NativeLibraries.getDefaultInstance().toByteArray())) .addEntry( InMemoryModuleEntry.ofFile( "resources.pb", ResourceTable.getDefaultInstance().toByteArray())) .build(); assertThat(bundleModule.getEntries()).isEmpty(); }
@Test public void nativeConfigs_defaultAndNonDefault_ok() throws Exception { ModuleSplit splitNonDefault = createModuleSplitBuilder() .setNativeConfig( nativeLibraries( targetedNativeDirectory("lib/mips", nativeDirectoryTargeting(AbiAlias.MIPS)))) .build(); ModuleSplit splitDefault = createModuleSplitBuilder().setNativeConfig(NativeLibraries.getDefaultInstance()).build(); // We don't care about the merged result, just that the merging succeeds. new ModuleSplitsToShardMerger(d8DexMerger, tmpDir) .mergeSingleShard( ImmutableList.of(splitNonDefault, splitDefault), NO_MAIN_DEX_LIST, createCache()); new ModuleSplitsToShardMerger(d8DexMerger, tmpDir) .mergeSingleShard( ImmutableList.of(splitDefault, splitNonDefault), NO_MAIN_DEX_LIST, createCache()); }
public BundleModuleBuilder setNativeConfig(NativeLibraries nativeConfig) { addFile("native.pb", nativeConfig.toByteArray()); return this; }
@Test public void generateTargetingForNativeLibraries_createsSingleDirectoryGroup() throws Exception { Collection<String> manyDirectories = Arrays.stream(AbiName.values()) .map(AbiName::getPlatformName) .map(abi -> "lib/" + abi) .collect(toImmutableList()); checkState(manyDirectories.size() > 1); // Otherwise this test is useless. NativeLibraries nativeTargeting = generator.generateTargetingForNativeLibraries(manyDirectories); List<TargetedNativeDirectory> directories = nativeTargeting.getDirectoryList(); assertThat(directories).hasSize(manyDirectories.size()); }
public static NativeLibraries nativeLibraries(TargetedNativeDirectory... nativeDirectories) { return NativeLibraries.newBuilder() .addAllDirectory(Lists.newArrayList(nativeDirectories)) .build(); }
@Test public void correctNativeProtoFile_parsedAndReturned() throws Exception { NativeLibraries nativeConfig = NativeLibraries.newBuilder() .addDirectory(TargetedNativeDirectory.newBuilder().setPath("native/x86")) .build(); BundleModule bundleModule = createMinimalModuleBuilder() .addEntry(InMemoryModuleEntry.ofFile("native.pb", nativeConfig.toByteArray())) .build(); assertThat(bundleModule.getNativeConfig()).hasValue(nativeConfig); }
@Override void addToModule(BundleModule.Builder module, InputStream inputStream) throws IOException { module.setNativeConfig(NativeLibraries.parseFrom(inputStream)); } },