Skip to content

Commit edad1ad

Browse files
michalgrmeta-codesync[bot]
authored andcommitted
support multiple manifests, one per abi
Summary: Make so-loader manifests libraries as well so that we can have separate manifest per ABI in multi-abi builds Reviewed By: adicatana Differential Revision: D93233770 fbshipit-source-id: f4dea917f5608d9c15b2ab4e8ec233b5b3dd164f
1 parent 7975b36 commit edad1ad

2 files changed

Lines changed: 85 additions & 2 deletions

File tree

java/com/facebook/soloader/DirectSplitSoSource.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ protected void prepare(int flags) throws IOException {
6363
if (mFeatureName == null) {
6464
throw new NullPointerException();
6565
}
66-
try (InputStream is =
67-
SoLoader.sApplicationContext.getAssets().open(mFeatureName + ".soloader-manifest")) {
66+
try (InputStream is = mSplit.openLib("lib" + mFeatureName + ".soloader-manifest.so")) {
6867
installManifest(Manifest.read(is));
6968
}
7069
}

java/com/facebook/soloader/Split.java

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@
1616

1717
package com.facebook.soloader;
1818

19+
import android.content.res.AssetFileDescriptor;
1920
import java.io.File;
21+
import java.io.FileNotFoundException;
2022
import java.io.IOException;
23+
import java.io.InputStream;
24+
import java.util.zip.ZipEntry;
25+
import java.util.zip.ZipFile;
2126

2227
/**
2328
* Represents an APK split that contains native libraries. There are two kinds:
@@ -30,6 +35,41 @@
3035
*/
3136
public abstract class Split {
3237

38+
/** An InputStream that closes an associated ZipFile when the stream is closed. */
39+
private static class ZipEntryInputStream extends InputStream {
40+
private final InputStream mDelegate;
41+
private final ZipFile mZipFile;
42+
43+
ZipEntryInputStream(InputStream delegate, ZipFile zipFile) {
44+
mDelegate = delegate;
45+
mZipFile = zipFile;
46+
}
47+
48+
@Override
49+
public int read() throws IOException {
50+
return mDelegate.read();
51+
}
52+
53+
@Override
54+
public int read(byte[] b, int off, int len) throws IOException {
55+
return mDelegate.read(b, off, len);
56+
}
57+
58+
@Override
59+
public int available() throws IOException {
60+
return mDelegate.available();
61+
}
62+
63+
@Override
64+
public void close() throws IOException {
65+
try {
66+
mDelegate.close();
67+
} finally {
68+
mZipFile.close();
69+
}
70+
}
71+
}
72+
3373
/** Returns the file system path to the split APK. */
3474
public abstract String getPath();
3575

@@ -48,6 +88,34 @@ public String getLibraryDirectory(String abi) {
4888
return getEntryPath("lib/" + abi + "/");
4989
}
5090

91+
/**
92+
* Opens a library from this split and returns an {@link InputStream} to read its contents. The
93+
* library is looked up under {@code lib/<abi>/<soName>} inside the archive. Uses the primary ABI.
94+
*/
95+
public InputStream openLib(String soName) throws IOException {
96+
return openLib(SoLoader.getPrimaryAbi(), soName);
97+
}
98+
99+
/**
100+
* Opens a library from this split and returns an {@link InputStream} to read its contents. The
101+
* library is looked up under {@code lib/<abi>/<soName>} inside the archive.
102+
*/
103+
public InputStream openLib(String abi, String soName) throws IOException {
104+
ZipFile zipFile = new ZipFile(getPath());
105+
String entryName = "lib/" + abi + "/" + soName;
106+
ZipEntry entry = zipFile.getEntry(entryName);
107+
if (entry == null) {
108+
zipFile.close();
109+
throw new FileNotFoundException("Entry not found: " + entryName + " in " + getPath());
110+
}
111+
InputStream is = zipFile.getInputStream(entry);
112+
if (is == null) {
113+
zipFile.close();
114+
throw new IOException("Failed to open entry: " + entryName + " in " + getPath());
115+
}
116+
return new ZipEntryInputStream(is, zipFile);
117+
}
118+
51119
/** Finds the installed ABI split for the given feature. */
52120
public static Installed findAbiSplit(String feature) {
53121
return new Installed(Splits.findAbiSplit(feature));
@@ -82,6 +150,22 @@ public String getPath() {
82150
return Splits.getSplitPath(mSplitName);
83151
}
84152

153+
private boolean isBaseFeature() {
154+
return "base.apk".equals(mSplitName) || mSplitName.startsWith("split_config.");
155+
}
156+
157+
@Override
158+
public InputStream openLib(String abi, String soName) throws IOException {
159+
if (isBaseFeature()) {
160+
AssetFileDescriptor afd =
161+
SoLoader.getApplicationContext()
162+
.getAssets()
163+
.openNonAssetFd("lib/" + abi + "/" + soName);
164+
return afd.createInputStream();
165+
}
166+
return super.openLib(abi, soName);
167+
}
168+
85169
@Override
86170
public String toString() {
87171
return "installed split:" + mSplitName;

0 commit comments

Comments
 (0)