mirror of
https://github.com/YTVanced/VancedMicroG
synced 2024-12-04 16:57:27 +00:00
Dynamite: Use filters for class loader merging
This commit is contained in:
parent
a746e79b91
commit
a830b5dd5d
3 changed files with 83 additions and 27 deletions
|
@ -23,14 +23,14 @@ import dalvik.system.PathClassLoader;
|
||||||
|
|
||||||
public class DynamiteContext extends ContextWrapper {
|
public class DynamiteContext extends ContextWrapper {
|
||||||
private static final String TAG = "DynamiteContext";
|
private static final String TAG = "DynamiteContext";
|
||||||
private String moduleId;
|
private DynamiteModuleInfo moduleInfo;
|
||||||
private Context originalContext;
|
private Context originalContext;
|
||||||
private Context gmsContext;
|
private Context gmsContext;
|
||||||
private DynamiteContext appContext;
|
private DynamiteContext appContext;
|
||||||
|
|
||||||
public DynamiteContext(String moduleId, Context base, Context gmsContext, DynamiteContext appContext) {
|
public DynamiteContext(DynamiteModuleInfo moduleInfo, Context base, Context gmsContext, DynamiteContext appContext) {
|
||||||
super(base);
|
super(base);
|
||||||
this.moduleId = moduleId;
|
this.moduleInfo = moduleInfo;
|
||||||
this.originalContext = base;
|
this.originalContext = base;
|
||||||
this.gmsContext = gmsContext;
|
this.gmsContext = gmsContext;
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
|
@ -38,7 +38,6 @@ public class DynamiteContext extends ContextWrapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClassLoader getClassLoader() {
|
public ClassLoader getClassLoader() {
|
||||||
if (new DynamiteModuleInfo(moduleId).isMergeClassLoader()) {
|
|
||||||
StringBuilder nativeLoaderDirs = new StringBuilder(gmsContext.getApplicationInfo().nativeLibraryDir);
|
StringBuilder nativeLoaderDirs = new StringBuilder(gmsContext.getApplicationInfo().nativeLibraryDir);
|
||||||
if (Build.VERSION.SDK_INT >= 23 && Process.is64Bit()) {
|
if (Build.VERSION.SDK_INT >= 23 && Process.is64Bit()) {
|
||||||
for (String abi : Build.SUPPORTED_64_BIT_ABIS) {
|
for (String abi : Build.SUPPORTED_64_BIT_ABIS) {
|
||||||
|
@ -51,10 +50,7 @@ public class DynamiteContext extends ContextWrapper {
|
||||||
} else {
|
} else {
|
||||||
nativeLoaderDirs.append(File.pathSeparator).append(gmsContext.getApplicationInfo().sourceDir).append("!/lib/").append(Build.CPU_ABI);
|
nativeLoaderDirs.append(File.pathSeparator).append(gmsContext.getApplicationInfo().sourceDir).append("!/lib/").append(Build.CPU_ABI);
|
||||||
}
|
}
|
||||||
return new PathClassLoader(gmsContext.getApplicationInfo().sourceDir, nativeLoaderDirs.toString(), originalContext.getClassLoader());
|
return new PathClassLoader(gmsContext.getApplicationInfo().sourceDir, nativeLoaderDirs.toString(), new FilteredClassLoader(originalContext.getClassLoader(), moduleInfo.getMergedClasses(), moduleInfo.getMergedPackages()));
|
||||||
} else {
|
|
||||||
return gmsContext.getClassLoader();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -75,17 +71,18 @@ public class DynamiteContext extends ContextWrapper {
|
||||||
@RequiresApi(24)
|
@RequiresApi(24)
|
||||||
@Override
|
@Override
|
||||||
public Context createDeviceProtectedStorageContext() {
|
public Context createDeviceProtectedStorageContext() {
|
||||||
return new DynamiteContext(moduleId, originalContext.createDeviceProtectedStorageContext(), gmsContext.createDeviceProtectedStorageContext(), appContext);
|
return new DynamiteContext(moduleInfo, originalContext.createDeviceProtectedStorageContext(), gmsContext.createDeviceProtectedStorageContext(), appContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DynamiteContext create(String moduleId, Context originalContext) {
|
public static DynamiteContext create(String moduleId, Context originalContext) {
|
||||||
try {
|
try {
|
||||||
Context gmsContext = originalContext.createPackageContext(Constants.GMS_PACKAGE_NAME, new DynamiteModuleInfo(moduleId).getCreatePackageOptions());
|
DynamiteModuleInfo moduleInfo = new DynamiteModuleInfo(moduleId);
|
||||||
|
Context gmsContext = originalContext.createPackageContext(Constants.GMS_PACKAGE_NAME, 0);
|
||||||
Context originalAppContext = originalContext.getApplicationContext();
|
Context originalAppContext = originalContext.getApplicationContext();
|
||||||
if (originalAppContext == null || originalAppContext == originalContext) {
|
if (originalAppContext == null || originalAppContext == originalContext) {
|
||||||
return new DynamiteContext(moduleId, originalContext, gmsContext, null);
|
return new DynamiteContext(moduleInfo, originalContext, gmsContext, null);
|
||||||
} else {
|
} else {
|
||||||
return new DynamiteContext(moduleId, originalContext, gmsContext, new DynamiteContext(moduleId, originalAppContext, gmsContext, null));
|
return new DynamiteContext(moduleInfo, originalContext, gmsContext, new DynamiteContext(moduleInfo, originalAppContext, gmsContext, null));
|
||||||
}
|
}
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
|
|
||||||
package com.google.android.gms.chimera.container;
|
package com.google.android.gms.chimera.container;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
import static android.content.Context.CONTEXT_IGNORE_SECURITY;
|
import static android.content.Context.CONTEXT_IGNORE_SECURITY;
|
||||||
import static android.content.Context.CONTEXT_INCLUDE_CODE;
|
import static android.content.Context.CONTEXT_INCLUDE_CODE;
|
||||||
|
|
||||||
|
@ -33,19 +36,19 @@ public class DynamiteModuleInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCreatePackageOptions() {
|
public Collection<String> getMergedPackages() {
|
||||||
try {
|
try {
|
||||||
return descriptor.getDeclaredField("CREATE_PACKAGE_OPTIONS").getInt(null);
|
return (Collection<String>) descriptor.getDeclaredField("MERGED_PACKAGES").get(null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return CONTEXT_INCLUDE_CODE | CONTEXT_IGNORE_SECURITY;
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMergeClassLoader() {
|
public Collection<String> getMergedClasses() {
|
||||||
try {
|
try {
|
||||||
return descriptor.getDeclaredField("MERGE_CLASS_LOADER").getBoolean(null);
|
return (Collection<String>) descriptor.getDeclaredField("MERGED_CLASSES").get(null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return false;
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.android.gms.chimera.container;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
public class FilteredClassLoader extends ClassLoader {
|
||||||
|
private static ClassLoader rootClassLoader;
|
||||||
|
private final Collection<String> allowedClasses;
|
||||||
|
private final Collection<String> allowedPackages;
|
||||||
|
|
||||||
|
static {
|
||||||
|
rootClassLoader = ClassLoader.getSystemClassLoader();
|
||||||
|
if (rootClassLoader == null) {
|
||||||
|
rootClassLoader = FilteredClassLoader.class.getClassLoader();
|
||||||
|
while (rootClassLoader.getParent() != null) {
|
||||||
|
rootClassLoader = rootClassLoader.getParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public FilteredClassLoader(ClassLoader parent, Collection<String> allowedClasses, Collection<String> allowedPackages) {
|
||||||
|
super(parent);
|
||||||
|
this.allowedClasses = new HashSet<>(allowedClasses);
|
||||||
|
this.allowedPackages = new HashSet<>(allowedPackages);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getPackageName(String name) {
|
||||||
|
int lastIndex = name.lastIndexOf(".");
|
||||||
|
if (lastIndex <= 0) return "";
|
||||||
|
return name.substring(0, lastIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getClassName(String name) {
|
||||||
|
int lastIndex = name.indexOf("$");
|
||||||
|
if (lastIndex <= 0) return name;
|
||||||
|
return name.substring(0, lastIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||||
|
if (name.startsWith("java.")) return rootClassLoader.loadClass(name);
|
||||||
|
if (allowedClasses.contains(name) || allowedClasses.contains(getClassName(name)))
|
||||||
|
return super.loadClass(name, resolve);
|
||||||
|
if (allowedClasses.contains("!" + name) || allowedClasses.contains("!" + getClassName(name)))
|
||||||
|
return rootClassLoader.loadClass(name);
|
||||||
|
if (allowedPackages.contains(getPackageName(name))) return super.loadClass(name, resolve);
|
||||||
|
return rootClassLoader.loadClass(name);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue