Merge "Introduce uses-native-library tag"
This commit is contained in:
@@ -48,17 +48,18 @@ public class ApplicationLoaders {
|
||||
ClassLoader parent, String classLoaderName) {
|
||||
return getClassLoaderWithSharedLibraries(zip, targetSdkVersion, isBundled,
|
||||
librarySearchPath, libraryPermittedPath, parent, classLoaderName,
|
||||
null);
|
||||
null, null);
|
||||
}
|
||||
|
||||
ClassLoader getClassLoaderWithSharedLibraries(
|
||||
String zip, int targetSdkVersion, boolean isBundled,
|
||||
String librarySearchPath, String libraryPermittedPath,
|
||||
ClassLoader parent, String classLoaderName,
|
||||
List<ClassLoader> sharedLibraries) {
|
||||
List<ClassLoader> sharedLibraries, List<String> nativeSharedLibraries) {
|
||||
// For normal usage the cache key used is the same as the zip path.
|
||||
return getClassLoader(zip, targetSdkVersion, isBundled, librarySearchPath,
|
||||
libraryPermittedPath, parent, zip, classLoaderName, sharedLibraries);
|
||||
libraryPermittedPath, parent, zip, classLoaderName, sharedLibraries,
|
||||
nativeSharedLibraries);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,14 +78,22 @@ public class ApplicationLoaders {
|
||||
return loader;
|
||||
}
|
||||
|
||||
// TODO(b/142191088): allow (Java) shared libraries to have <uses-native-library>
|
||||
// Until that is supported, assume that all native shared libraries are used.
|
||||
// "ALL" is a magic string that libnativeloader uses to unconditionally add all available
|
||||
// native shared libraries to the classloader.
|
||||
List<String> nativeSharedLibraries = new ArrayList<>();
|
||||
nativeSharedLibraries.add("ALL");
|
||||
return getClassLoaderWithSharedLibraries(zip, targetSdkVersion, isBundled,
|
||||
librarySearchPath, libraryPermittedPath, parent, classLoaderName, sharedLibraries);
|
||||
librarySearchPath, libraryPermittedPath, parent, classLoaderName, sharedLibraries,
|
||||
nativeSharedLibraries);
|
||||
}
|
||||
|
||||
private ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
|
||||
String librarySearchPath, String libraryPermittedPath,
|
||||
ClassLoader parent, String cacheKey,
|
||||
String classLoaderName, List<ClassLoader> sharedLibraries) {
|
||||
String classLoaderName, List<ClassLoader> sharedLibraries,
|
||||
List<String> nativeSharedLibraries) {
|
||||
/*
|
||||
* This is the parent we use if they pass "null" in. In theory
|
||||
* this should be the "system" class loader; in practice we
|
||||
@@ -113,7 +122,8 @@ public class ApplicationLoaders {
|
||||
|
||||
ClassLoader classloader = ClassLoaderFactory.createClassLoader(
|
||||
zip, librarySearchPath, libraryPermittedPath, parent,
|
||||
targetSdkVersion, isBundled, classLoaderName, sharedLibraries);
|
||||
targetSdkVersion, isBundled, classLoaderName, sharedLibraries,
|
||||
nativeSharedLibraries);
|
||||
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
|
||||
@@ -185,7 +195,8 @@ public class ApplicationLoaders {
|
||||
// assume cached libraries work with current sdk since they are built-in
|
||||
ClassLoader classLoader = getClassLoader(path, Build.VERSION.SDK_INT, true /*isBundled*/,
|
||||
null /*librarySearchPath*/, null /*libraryPermittedPath*/, null /*parent*/,
|
||||
null /*cacheKey*/, null /*classLoaderName*/, sharedLibraries /*sharedLibraries*/);
|
||||
null /*cacheKey*/, null /*classLoaderName*/, sharedLibraries /*sharedLibraries*/,
|
||||
null /* nativeSharedLibraries */);
|
||||
|
||||
if (classLoader == null) {
|
||||
// bad configuration or break in classloading code
|
||||
@@ -255,7 +266,8 @@ public class ApplicationLoaders {
|
||||
// The cache key is passed separately to enable the stub WebView to be cached under the
|
||||
// stub's APK path, when the actual package path is the donor APK.
|
||||
return getClassLoader(packagePath, Build.VERSION.SDK_INT, false, libsPath, null, null,
|
||||
cacheKey, null /* classLoaderName */, null /* sharedLibraries */);
|
||||
cacheKey, null /* classLoaderName */, null /* sharedLibraries */,
|
||||
null /* nativeSharedLibraries */);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -412,6 +412,12 @@ public final class LoadedApk {
|
||||
return;
|
||||
}
|
||||
for (SharedLibraryInfo lib : sharedLibraries) {
|
||||
if (lib.isNative()) {
|
||||
// Native shared lib doesn't contribute to the native lib search path. Its name is
|
||||
// sent to libnativeloader and then the native shared lib is exported from the
|
||||
// default linker namespace.
|
||||
continue;
|
||||
}
|
||||
List<String> paths = lib.getAllCodePaths();
|
||||
outSeenPaths.addAll(paths);
|
||||
for (String path : paths) {
|
||||
@@ -696,6 +702,12 @@ public final class LoadedApk {
|
||||
}
|
||||
List<ClassLoader> loaders = new ArrayList<>();
|
||||
for (SharedLibraryInfo info : sharedLibraries) {
|
||||
if (info.isNative()) {
|
||||
// Native shared lib doesn't contribute to the native lib search path. Its name is
|
||||
// sent to libnativeloader and then the native shared lib is exported from the
|
||||
// default linker namespace.
|
||||
continue;
|
||||
}
|
||||
loaders.add(createSharedLibraryLoader(
|
||||
info, isBundledApp, librarySearchPath, libraryPermittedPath));
|
||||
}
|
||||
@@ -898,10 +910,19 @@ public final class LoadedApk {
|
||||
mApplicationInfo.sharedLibraryInfos, isBundledApp, librarySearchPath,
|
||||
libraryPermittedPath);
|
||||
|
||||
List<String> nativeSharedLibraries = new ArrayList<>();
|
||||
if (mApplicationInfo.sharedLibraryInfos != null) {
|
||||
for (SharedLibraryInfo info : mApplicationInfo.sharedLibraryInfos) {
|
||||
if (info.isNative()) {
|
||||
nativeSharedLibraries.add(info.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoaderWithSharedLibraries(
|
||||
zip, mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
|
||||
libraryPermittedPath, mBaseClassLoader,
|
||||
mApplicationInfo.classLoaderName, sharedLibraries);
|
||||
mApplicationInfo.classLoaderName, sharedLibraries, nativeSharedLibraries);
|
||||
mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);
|
||||
|
||||
setThreadPolicy(oldPolicy);
|
||||
|
||||
@@ -79,6 +79,7 @@ public final class SharedLibraryInfo implements Parcelable {
|
||||
|
||||
private final long mVersion;
|
||||
private final @Type int mType;
|
||||
private final boolean mIsNative;
|
||||
private final VersionedPackage mDeclaringPackage;
|
||||
private final List<VersionedPackage> mDependentPackages;
|
||||
private List<SharedLibraryInfo> mDependencies;
|
||||
@@ -93,13 +94,14 @@ public final class SharedLibraryInfo implements Parcelable {
|
||||
* @param type The lib type.
|
||||
* @param declaringPackage The package that declares the library.
|
||||
* @param dependentPackages The packages that depend on the library.
|
||||
* @param isNative indicate if this shared lib is a native lib or not (i.e. java)
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public SharedLibraryInfo(String path, String packageName, List<String> codePaths,
|
||||
String name, long version, int type,
|
||||
VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages,
|
||||
List<SharedLibraryInfo> dependencies) {
|
||||
List<SharedLibraryInfo> dependencies, boolean isNative) {
|
||||
mPath = path;
|
||||
mPackageName = packageName;
|
||||
mCodePaths = codePaths;
|
||||
@@ -109,6 +111,16 @@ public final class SharedLibraryInfo implements Parcelable {
|
||||
mDeclaringPackage = declaringPackage;
|
||||
mDependentPackages = dependentPackages;
|
||||
mDependencies = dependencies;
|
||||
mIsNative = isNative;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public SharedLibraryInfo(String path, String packageName, List<String> codePaths,
|
||||
String name, long version, int type,
|
||||
VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages,
|
||||
List<SharedLibraryInfo> dependencies) {
|
||||
this(path, packageName, codePaths, name, version, type, declaringPackage, dependentPackages,
|
||||
dependencies, false /* isNative */);
|
||||
}
|
||||
|
||||
private SharedLibraryInfo(Parcel parcel) {
|
||||
@@ -125,6 +137,7 @@ public final class SharedLibraryInfo implements Parcelable {
|
||||
mDeclaringPackage = parcel.readParcelable(null);
|
||||
mDependentPackages = parcel.readArrayList(null);
|
||||
mDependencies = parcel.createTypedArrayList(SharedLibraryInfo.CREATOR);
|
||||
mIsNative = parcel.readBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,6 +149,15 @@ public final class SharedLibraryInfo implements Parcelable {
|
||||
return mType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether this library is a native shared library or not.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public boolean isNative() {
|
||||
return mIsNative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the library name an app defines in its manifest
|
||||
* to depend on the library.
|
||||
@@ -320,6 +342,7 @@ public final class SharedLibraryInfo implements Parcelable {
|
||||
parcel.writeParcelable(mDeclaringPackage, flags);
|
||||
parcel.writeList(mDependentPackages);
|
||||
parcel.writeTypedList(mDependencies);
|
||||
parcel.writeBoolean(mIsNative);
|
||||
}
|
||||
|
||||
private static String typeToString(int type) {
|
||||
|
||||
@@ -92,6 +92,10 @@ public interface ParsingPackage extends ParsingPackageRead {
|
||||
|
||||
ParsingPackage addUsesOptionalLibrary(String libraryName);
|
||||
|
||||
ParsingPackage addUsesNativeLibrary(String libraryName);
|
||||
|
||||
ParsingPackage addUsesOptionalNativeLibrary(String libraryName);
|
||||
|
||||
ParsingPackage addUsesStaticLibrary(String libraryName);
|
||||
|
||||
ParsingPackage addUsesStaticLibraryCertDigests(String[] certSha256Digests);
|
||||
@@ -219,6 +223,8 @@ public interface ParsingPackage extends ParsingPackageRead {
|
||||
|
||||
ParsingPackage removeUsesOptionalLibrary(String libraryName);
|
||||
|
||||
ParsingPackage removeUsesOptionalNativeLibrary(String libraryName);
|
||||
|
||||
ParsingPackage setAnyDensity(int anyDensity);
|
||||
|
||||
ParsingPackage setAppComponentFactory(String appComponentFactory);
|
||||
|
||||
@@ -184,6 +184,13 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
|
||||
@DataClass.ParcelWith(ForInternedStringList.class)
|
||||
protected List<String> usesOptionalLibraries = emptyList();
|
||||
|
||||
@NonNull
|
||||
@DataClass.ParcelWith(ForInternedStringList.class)
|
||||
protected List<String> usesNativeLibraries = emptyList();
|
||||
@NonNull
|
||||
@DataClass.ParcelWith(ForInternedStringList.class)
|
||||
protected List<String> usesOptionalNativeLibraries = emptyList();
|
||||
|
||||
@NonNull
|
||||
@DataClass.ParcelWith(ForInternedStringList.class)
|
||||
private List<String> usesStaticLibraries = emptyList();
|
||||
@@ -668,6 +675,27 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ParsingPackageImpl addUsesOptionalNativeLibrary(String libraryName) {
|
||||
this.usesOptionalNativeLibraries = CollectionUtils.add(this.usesOptionalNativeLibraries,
|
||||
TextUtils.safeIntern(libraryName));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ParsingPackageImpl addUsesNativeLibrary(String libraryName) {
|
||||
this.usesNativeLibraries = CollectionUtils.add(this.usesNativeLibraries,
|
||||
TextUtils.safeIntern(libraryName));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override public ParsingPackageImpl removeUsesOptionalNativeLibrary(String libraryName) {
|
||||
this.usesOptionalNativeLibraries = CollectionUtils.remove(this.usesOptionalNativeLibraries,
|
||||
libraryName);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParsingPackageImpl addUsesStaticLibrary(String libraryName) {
|
||||
this.usesStaticLibraries = CollectionUtils.add(this.usesStaticLibraries,
|
||||
@@ -982,6 +1010,8 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
|
||||
sForInternedStringList.parcel(this.libraryNames, dest, flags);
|
||||
sForInternedStringList.parcel(this.usesLibraries, dest, flags);
|
||||
sForInternedStringList.parcel(this.usesOptionalLibraries, dest, flags);
|
||||
sForInternedStringList.parcel(this.usesNativeLibraries, dest, flags);
|
||||
sForInternedStringList.parcel(this.usesOptionalNativeLibraries, dest, flags);
|
||||
sForInternedStringList.parcel(this.usesStaticLibraries, dest, flags);
|
||||
dest.writeLongArray(this.usesStaticLibrariesVersions);
|
||||
|
||||
@@ -1144,6 +1174,8 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
|
||||
this.libraryNames = sForInternedStringList.unparcel(in);
|
||||
this.usesLibraries = sForInternedStringList.unparcel(in);
|
||||
this.usesOptionalLibraries = sForInternedStringList.unparcel(in);
|
||||
this.usesNativeLibraries = sForInternedStringList.unparcel(in);
|
||||
this.usesOptionalNativeLibraries = sForInternedStringList.unparcel(in);
|
||||
this.usesStaticLibraries = sForInternedStringList.unparcel(in);
|
||||
this.usesStaticLibrariesVersions = in.createLongArray();
|
||||
|
||||
@@ -1415,6 +1447,18 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
|
||||
return usesOptionalLibraries;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public List<String> getUsesNativeLibraries() {
|
||||
return usesNativeLibraries;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public List<String> getUsesOptionalNativeLibraries() {
|
||||
return usesOptionalNativeLibraries;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public List<String> getUsesStaticLibraries() {
|
||||
|
||||
@@ -230,6 +230,19 @@ public interface ParsingPackageRead extends Parcelable {
|
||||
@NonNull
|
||||
List<String> getUsesOptionalLibraries();
|
||||
|
||||
/** @see R.styleabele#AndroidManifestUsesNativeLibrary */
|
||||
@NonNull
|
||||
List<String> getUsesNativeLibraries();
|
||||
|
||||
/**
|
||||
* Like {@link #getUsesNativeLibraries()}, but marked optional by setting
|
||||
* {@link R.styleable#AndroidManifestUsesNativeLibrary_required} to false . Application is
|
||||
* expected to handle absence manually.
|
||||
* @see R.styleable#AndroidManifestUsesNativeLibrary
|
||||
*/
|
||||
@NonNull
|
||||
List<String> getUsesOptionalNativeLibraries();
|
||||
|
||||
/**
|
||||
* TODO(b/135203078): Move static library stuff to an inner data class
|
||||
* @see R.styleable#AndroidManifestUsesStaticLibrary
|
||||
|
||||
@@ -701,6 +701,8 @@ public class ParsingPackageUtils {
|
||||
return parseUsesStaticLibrary(input, pkg, res, parser);
|
||||
case "uses-library":
|
||||
return parseUsesLibrary(input, pkg, res, parser);
|
||||
case "uses-native-library":
|
||||
return parseUsesNativeLibrary(input, pkg, res, parser);
|
||||
case "uses-package":
|
||||
// Dependencies for app installers; we don't currently try to
|
||||
// enforce this.
|
||||
@@ -2017,6 +2019,8 @@ public class ParsingPackageUtils {
|
||||
return parseUsesStaticLibrary(input, pkg, res, parser);
|
||||
case "uses-library":
|
||||
return parseUsesLibrary(input, pkg, res, parser);
|
||||
case "uses-native-library":
|
||||
return parseUsesNativeLibrary(input, pkg, res, parser);
|
||||
case "processes":
|
||||
return parseProcesses(input, pkg, res, parser, mSeparateProcesses, flags);
|
||||
case "uses-package":
|
||||
@@ -2177,6 +2181,37 @@ public class ParsingPackageUtils {
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static ParseResult<ParsingPackage> parseUsesNativeLibrary(ParseInput input,
|
||||
ParsingPackage pkg, Resources res, XmlResourceParser parser) {
|
||||
TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesNativeLibrary);
|
||||
try {
|
||||
// Note: don't allow this value to be a reference to a resource
|
||||
// that may change.
|
||||
String lname = sa.getNonResourceString(
|
||||
R.styleable.AndroidManifestUsesNativeLibrary_name);
|
||||
boolean req = sa.getBoolean(R.styleable.AndroidManifestUsesNativeLibrary_required,
|
||||
true);
|
||||
|
||||
if (lname != null) {
|
||||
if (req) {
|
||||
// Upgrade to treat as stronger constraint
|
||||
pkg.addUsesNativeLibrary(lname)
|
||||
.removeUsesOptionalNativeLibrary(lname);
|
||||
} else {
|
||||
// Ignore if someone already defined as required
|
||||
if (!ArrayUtils.contains(pkg.getUsesNativeLibraries(), lname)) {
|
||||
pkg.addUsesOptionalNativeLibrary(lname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return input.success(pkg);
|
||||
} finally {
|
||||
sa.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static ParseResult<ParsingPackage> parseProcesses(ParseInput input, ParsingPackage pkg,
|
||||
Resources res, XmlResourceParser parser, String[] separateProcesses, int flags)
|
||||
|
||||
@@ -101,7 +101,7 @@ public class ClassLoaderFactory {
|
||||
String librarySearchPath, String libraryPermittedPath, ClassLoader parent,
|
||||
int targetSdkVersion, boolean isNamespaceShared, String classLoaderName) {
|
||||
return createClassLoader(dexPath, librarySearchPath, libraryPermittedPath,
|
||||
parent, targetSdkVersion, isNamespaceShared, classLoaderName, null);
|
||||
parent, targetSdkVersion, isNamespaceShared, classLoaderName, null, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,18 +111,24 @@ public class ClassLoaderFactory {
|
||||
public static ClassLoader createClassLoader(String dexPath,
|
||||
String librarySearchPath, String libraryPermittedPath, ClassLoader parent,
|
||||
int targetSdkVersion, boolean isNamespaceShared, String classLoaderName,
|
||||
List<ClassLoader> sharedLibraries) {
|
||||
List<ClassLoader> sharedLibraries, List<String> nativeSharedLibraries) {
|
||||
|
||||
final ClassLoader classLoader = createClassLoader(dexPath, librarySearchPath, parent,
|
||||
classLoaderName, sharedLibraries);
|
||||
|
||||
String sonameList = "";
|
||||
if (nativeSharedLibraries != null) {
|
||||
sonameList = String.join(":", nativeSharedLibraries);
|
||||
}
|
||||
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "createClassloaderNamespace");
|
||||
String errorMessage = createClassloaderNamespace(classLoader,
|
||||
targetSdkVersion,
|
||||
librarySearchPath,
|
||||
libraryPermittedPath,
|
||||
isNamespaceShared,
|
||||
dexPath);
|
||||
dexPath,
|
||||
sonameList);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
|
||||
if (errorMessage != null) {
|
||||
@@ -139,5 +145,6 @@ public class ClassLoaderFactory {
|
||||
String librarySearchPath,
|
||||
String libraryPermittedPath,
|
||||
boolean isNamespaceShared,
|
||||
String dexPath);
|
||||
String dexPath,
|
||||
String sonameList);
|
||||
}
|
||||
|
||||
@@ -49,10 +49,12 @@ import libcore.io.IoUtils;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -104,11 +106,17 @@ public class SystemConfig {
|
||||
public final String name;
|
||||
public final String filename;
|
||||
public final String[] dependencies;
|
||||
public final boolean isNative;
|
||||
|
||||
SharedLibraryEntry(String name, String filename, String[] dependencies) {
|
||||
this(name, filename, dependencies, false /* isNative */);
|
||||
}
|
||||
|
||||
SharedLibraryEntry(String name, String filename, String[] dependencies, boolean isNative) {
|
||||
this.name = name;
|
||||
this.filename = filename;
|
||||
this.dependencies = dependencies;
|
||||
this.isNative = isNative;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,6 +465,7 @@ public class SystemConfig {
|
||||
log.traceBegin("readAllPermissions");
|
||||
try {
|
||||
readAllPermissions();
|
||||
readPublicNativeLibrariesList();
|
||||
} finally {
|
||||
log.traceEnd();
|
||||
}
|
||||
@@ -1513,6 +1522,37 @@ public class SystemConfig {
|
||||
}
|
||||
}
|
||||
|
||||
private void readPublicNativeLibrariesList() {
|
||||
readPublicLibrariesListFile(new File("/vendor/etc/public.libraries.txt"));
|
||||
String[] dirs = {"/system/etc", "/system_ext/etc", "/product/etc"};
|
||||
for (String dir : dirs) {
|
||||
for (File f : (new File(dir)).listFiles()) {
|
||||
String name = f.getName();
|
||||
if (name.startsWith("public.libraries-") && name.endsWith(".txt")) {
|
||||
readPublicLibrariesListFile(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readPublicLibrariesListFile(File listFile) {
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(listFile))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
if (line.isEmpty() || line.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
// Line format is <soname> [abi]. We take the soname part.
|
||||
String soname = line.trim().split(" ")[0];
|
||||
SharedLibraryEntry entry = new SharedLibraryEntry(
|
||||
soname, soname, new String[0], true);
|
||||
mSharedLibraries.put(entry.name, entry);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Slog.w(TAG, "Failed to read public libraries file " + listFile, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSystemProcess() {
|
||||
return Process.myUid() == Process.SYSTEM_UID;
|
||||
}
|
||||
|
||||
@@ -28,16 +28,19 @@ static jstring createClassloaderNamespace_native(JNIEnv* env,
|
||||
jstring librarySearchPath,
|
||||
jstring libraryPermittedPath,
|
||||
jboolean isShared,
|
||||
jstring dexPath) {
|
||||
jstring dexPath,
|
||||
jstring sonameList) {
|
||||
return android::CreateClassLoaderNamespace(env, targetSdkVersion,
|
||||
classLoader, isShared == JNI_TRUE,
|
||||
dexPath,
|
||||
librarySearchPath, libraryPermittedPath);
|
||||
librarySearchPath,
|
||||
libraryPermittedPath,
|
||||
sonameList);
|
||||
}
|
||||
|
||||
static const JNINativeMethod g_methods[] = {
|
||||
{ "createClassloaderNamespace",
|
||||
"(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;)Ljava/lang/String;",
|
||||
"(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
|
||||
reinterpret_cast<void*>(createClassloaderNamespace_native) },
|
||||
};
|
||||
|
||||
|
||||
@@ -2173,6 +2173,29 @@
|
||||
<attr name="required" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- The <code>uses-native-library</code> specifies a native shared library that this
|
||||
package requires to be linked against. Specifying this flag tells the
|
||||
system to make the native library to be available to your app.
|
||||
|
||||
<p>On devices running R or lower, this is ignored and the app has access to all
|
||||
the public native shared libraries that are exported from the platform. This is
|
||||
also ignored if the app is targeting R or lower.
|
||||
|
||||
<p>This appears as a child tag of the
|
||||
{@link #AndroidManifestApplication application} tag. -->
|
||||
<declare-styleable name="AndroidManifestUsesNativeLibrary" parent="AndroidManifestApplication">
|
||||
<!-- Required name of the library you use. -->
|
||||
<attr name="name" />
|
||||
<!-- Specify whether this native library is required for the application.
|
||||
The default is true, meaning the application requires the
|
||||
library, and does not want to be installed on devices that
|
||||
don't support it. If you set this to false, then this will
|
||||
allow the application to be installed even if the library
|
||||
doesn't exist, and you will need to check for its presence
|
||||
dynamically at runtime. -->
|
||||
<attr name="required" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- The <code>uses-static-library</code> specifies a shared <strong>static</strong>
|
||||
library that this package requires to be statically linked against. Specifying
|
||||
this tag tells the system to include this library's code in your class loader.
|
||||
|
||||
@@ -651,6 +651,23 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
private static final long THROW_EXCEPTION_ON_REQUIRE_INSTALL_PACKAGES_TO_ADD_INSTALLER_PACKAGE =
|
||||
150857253;
|
||||
|
||||
/**
|
||||
* Apps targeting Android S and above need to declare dependencies to the public native
|
||||
* shared libraries that are defined by the device maker using {@code uses-native-library} tag
|
||||
* in its {@code AndroidManifest.xml}.
|
||||
*
|
||||
* If any of the dependencies cannot be satisfied, i.e. one of the dependency doesn't exist,
|
||||
* the package manager rejects to install the app. The dependency can be specified as optional
|
||||
* using {@code android:required} attribute in the tag, in which case failing to satisfy the
|
||||
* dependency doesn't stop the installation.
|
||||
* <p>Once installed, an app is provided with only the native shared libraries that are
|
||||
* specified in the app manifest. {@code dlopen}ing a native shared library that doesn't appear
|
||||
* in the app manifest will fail even if it actually exists on the device.
|
||||
*/
|
||||
@ChangeId
|
||||
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
|
||||
private static final long ENFORCE_NATIVE_SHARED_LIBRARY_DEPENDENCIES = 142191088;
|
||||
|
||||
public static final String PLATFORM_PACKAGE_NAME = "android";
|
||||
|
||||
private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
|
||||
@@ -2952,9 +2969,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
= systemConfig.getSharedLibraries();
|
||||
final int builtInLibCount = libConfig.size();
|
||||
for (int i = 0; i < builtInLibCount; i++) {
|
||||
String name = libConfig.keyAt(i);
|
||||
SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i);
|
||||
addBuiltInSharedLibraryLocked(entry.filename, name);
|
||||
addBuiltInSharedLibraryLocked(libConfig.valueAt(i));
|
||||
}
|
||||
|
||||
// Now that we have added all the libraries, iterate again to add dependency
|
||||
@@ -10486,6 +10502,19 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
null, null, pkg.getPackageName(), false, pkg.getTargetSdkVersion(),
|
||||
usesLibraryInfos, availablePackages, existingLibraries, newLibraries);
|
||||
}
|
||||
// TODO(b/160928779) gate this behavior using ENFORCE_NATIVE_SHARED_LIBRARY_DEPENDENCIES
|
||||
if (pkg.getTargetSdkVersion() > 30) {
|
||||
if (!pkg.getUsesNativeLibraries().isEmpty() && pkg.getTargetSdkVersion() > 30) {
|
||||
usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesNativeLibraries(), null,
|
||||
null, pkg.getPackageName(), true, pkg.getTargetSdkVersion(),
|
||||
usesLibraryInfos, availablePackages, existingLibraries, newLibraries);
|
||||
}
|
||||
if (!pkg.getUsesOptionalNativeLibraries().isEmpty()) {
|
||||
usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesOptionalNativeLibraries(),
|
||||
null, null, pkg.getPackageName(), false, pkg.getTargetSdkVersion(),
|
||||
usesLibraryInfos, availablePackages, existingLibraries, newLibraries);
|
||||
}
|
||||
}
|
||||
return usesLibraryInfos;
|
||||
}
|
||||
|
||||
@@ -12177,15 +12206,16 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private boolean addBuiltInSharedLibraryLocked(String path, String name) {
|
||||
if (nonStaticSharedLibExistsLocked(name)) {
|
||||
private boolean addBuiltInSharedLibraryLocked(SystemConfig.SharedLibraryEntry entry) {
|
||||
if (nonStaticSharedLibExistsLocked(entry.name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SharedLibraryInfo libraryInfo = new SharedLibraryInfo(path, null, null, name,
|
||||
(long) SharedLibraryInfo.VERSION_UNDEFINED, SharedLibraryInfo.TYPE_BUILTIN,
|
||||
new VersionedPackage(PLATFORM_PACKAGE_NAME, (long) 0),
|
||||
null, null);
|
||||
SharedLibraryInfo libraryInfo = new SharedLibraryInfo(entry.filename, null, null,
|
||||
entry.name, (long) SharedLibraryInfo.VERSION_UNDEFINED,
|
||||
SharedLibraryInfo.TYPE_BUILTIN,
|
||||
new VersionedPackage(PLATFORM_PACKAGE_NAME, (long)0), null, null,
|
||||
entry.isNative);
|
||||
|
||||
commitSharedLibraryInfoLocked(libraryInfo);
|
||||
return true;
|
||||
@@ -21900,7 +21930,11 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
pw.print(" -> ");
|
||||
}
|
||||
if (libraryInfo.getPath() != null) {
|
||||
pw.print(" (jar) ");
|
||||
if (libraryInfo.isNative()) {
|
||||
pw.print(" (so) ");
|
||||
} else {
|
||||
pw.print(" (jar) ");
|
||||
}
|
||||
pw.print(libraryInfo.getPath());
|
||||
} else {
|
||||
pw.print(" (apk) ");
|
||||
|
||||
@@ -4784,6 +4784,23 @@ public final class Settings {
|
||||
}
|
||||
}
|
||||
|
||||
List<String> usesNativeLibraries = pkg.getUsesNativeLibraries();
|
||||
if (usesNativeLibraries.size() > 0) {
|
||||
pw.print(prefix); pw.println(" usesNativeLibraries:");
|
||||
for (int i=0; i< usesNativeLibraries.size(); i++) {
|
||||
pw.print(prefix); pw.print(" "); pw.println(usesNativeLibraries.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
List<String> usesOptionalNativeLibraries = pkg.getUsesOptionalNativeLibraries();
|
||||
if (usesOptionalNativeLibraries.size() > 0) {
|
||||
pw.print(prefix); pw.println(" usesOptionalNativeLibraries:");
|
||||
for (int i=0; i< usesOptionalNativeLibraries.size(); i++) {
|
||||
pw.print(prefix); pw.print(" ");
|
||||
pw.println(usesOptionalNativeLibraries.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
List<String> usesLibraryFiles = ps.getPkgState().getUsesLibraryFiles();
|
||||
if (usesLibraryFiles.size() > 0) {
|
||||
pw.print(prefix); pw.println(" usesLibraryFiles:");
|
||||
|
||||
@@ -252,6 +252,19 @@ public interface AndroidPackage extends PkgAppInfo, PkgPackageInfo, ParsingPacka
|
||||
@NonNull
|
||||
List<String> getUsesOptionalLibraries();
|
||||
|
||||
/** @see R.styleabele#AndroidManifestUsesNativeLibrary */
|
||||
@NonNull
|
||||
List<String> getUsesNativeLibraries();
|
||||
|
||||
/**
|
||||
* Like {@link #getUsesNativeLibraries()}, but marked optional by setting
|
||||
* {@link R.styleable#AndroidManifestUsesNativeLibrary_required} to false . Application is
|
||||
* expected to handle absence manually.
|
||||
* @see R.styleable#AndroidManifestUsesNativeLibrary
|
||||
*/
|
||||
@NonNull
|
||||
List<String> getUsesOptionalNativeLibraries();
|
||||
|
||||
/**
|
||||
* TODO(b/135203078): Move static library stuff to an inner data class
|
||||
* @see R.styleable#AndroidManifestUsesStaticLibrary
|
||||
|
||||
@@ -1405,6 +1405,29 @@ class UsesStaticLibrary : public ManifestExtractor::Element {
|
||||
}
|
||||
};
|
||||
|
||||
/** Represents <uses-native-library> elements. **/
|
||||
class UsesNativeLibrary : public ManifestExtractor::Element {
|
||||
public:
|
||||
UsesNativeLibrary() = default;
|
||||
std::string name;
|
||||
int required;
|
||||
|
||||
void Extract(xml::Element* element) override {
|
||||
auto parent_stack = extractor()->parent_stack();
|
||||
if (parent_stack.size() > 0 && ElementCast<Application>(parent_stack[0])) {
|
||||
name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
|
||||
required = GetAttributeIntegerDefault(FindAttribute(element, REQUIRED_ATTR), 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Print(text::Printer* printer) override {
|
||||
if (!name.empty()) {
|
||||
printer->Print(StringPrintf("uses-native-library%s:'%s'\n",
|
||||
(required == 0) ? "-not-required" : "", name.data()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents <meta-data> elements. These tags are only printed when a flag is passed in to
|
||||
* explicitly enable meta data printing.
|
||||
@@ -2245,6 +2268,7 @@ T* ElementCast(ManifestExtractor::Element* element) {
|
||||
{"uses-static-library", std::is_base_of<UsesStaticLibrary, T>::value},
|
||||
{"additional-certificate", std::is_base_of<AdditionalCertificate, T>::value},
|
||||
{"uses-sdk", std::is_base_of<UsesSdkBadging, T>::value},
|
||||
{"uses-native-library", std::is_base_of<UsesNativeLibrary, T>::value},
|
||||
};
|
||||
|
||||
auto check = kTagCheck.find(element->tag());
|
||||
@@ -2295,6 +2319,7 @@ std::unique_ptr<ManifestExtractor::Element> ManifestExtractor::Element::Inflate(
|
||||
{"uses-package", &CreateType<UsesPackage>},
|
||||
{"additional-certificate", &CreateType<AdditionalCertificate>},
|
||||
{"uses-sdk", &CreateType<UsesSdkBadging>},
|
||||
{"uses-native-library", &CreateType<UsesNativeLibrary>},
|
||||
};
|
||||
|
||||
// Attempt to map the xml tag to a element inflater
|
||||
|
||||
@@ -422,6 +422,7 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
|
||||
application_action.Action(OptionalNameIsJavaClassName);
|
||||
|
||||
application_action["uses-library"].Action(RequiredNameIsNotEmpty);
|
||||
application_action["uses-native-library"].Action(RequiredNameIsNotEmpty);
|
||||
application_action["library"].Action(RequiredNameIsNotEmpty);
|
||||
application_action["profileable"];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user