Fix module loading (#2418)
This commit is contained in:
parent
55afed974d
commit
516a4aa99d
|
|
@ -75,10 +75,10 @@ public abstract class XC_MethodHook extends XCallback {
|
||||||
* @param param Information about the method call.
|
* @param param Information about the method call.
|
||||||
* @throws Throwable Everything the callback throws is caught and logged.
|
* @throws Throwable Everything the callback throws is caught and logged.
|
||||||
*/
|
*/
|
||||||
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
|
protected void beforeHookedMethod(MethodHookParam<?> param) throws Throwable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void callBeforeHookedMethod(MethodHookParam param) throws Throwable {
|
public void callBeforeHookedMethod(MethodHookParam<?> param) throws Throwable {
|
||||||
beforeHookedMethod(param);
|
beforeHookedMethod(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,10 +93,10 @@ public abstract class XC_MethodHook extends XCallback {
|
||||||
* @param param Information about the method call.
|
* @param param Information about the method call.
|
||||||
* @throws Throwable Everything the callback throws is caught and logged.
|
* @throws Throwable Everything the callback throws is caught and logged.
|
||||||
*/
|
*/
|
||||||
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
protected void afterHookedMethod(MethodHookParam<?> param) throws Throwable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void callAfterHookedMethod(MethodHookParam param) throws Throwable {
|
public void callAfterHookedMethod(MethodHookParam<?> param) throws Throwable {
|
||||||
afterHookedMethod(param);
|
afterHookedMethod(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ import java.security.MessageDigest;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import de.robv.android.xposed.services.FileResult;
|
import de.robv.android.xposed.services.FileResult;
|
||||||
|
|
@ -160,29 +161,27 @@ public final class XSharedPreferences implements SharedPreferences {
|
||||||
*/
|
*/
|
||||||
public XSharedPreferences(String packageName, String prefFileName) {
|
public XSharedPreferences(String packageName, String prefFileName) {
|
||||||
boolean newModule = false;
|
boolean newModule = false;
|
||||||
Set<String> modules = XposedInit.getLoadedModules();
|
var m = XposedInit.getLoadedModules().getOrDefault(packageName, Optional.empty());
|
||||||
for (String m : modules) {
|
if (m.isPresent()) {
|
||||||
if (m.contains("/" + packageName + "-")) {
|
boolean isModule = false;
|
||||||
boolean isModule = false;
|
int xposedminversion = -1;
|
||||||
int xposedminversion = -1;
|
boolean xposedsharedprefs = false;
|
||||||
boolean xposedsharedprefs = false;
|
try {
|
||||||
try {
|
Map<String, Object> metaData = MetaDataReader.getMetaData(new File(m.get()));
|
||||||
Map<String, Object> metaData = MetaDataReader.getMetaData(new File(m));
|
isModule = metaData.containsKey("xposedminversion");
|
||||||
isModule = metaData.containsKey("xposedminversion");
|
if (isModule) {
|
||||||
if (isModule) {
|
Object minVersionRaw = metaData.get("xposedminversion");
|
||||||
Object minVersionRaw = metaData.get("xposedminversion");
|
if (minVersionRaw instanceof Integer) {
|
||||||
if (minVersionRaw instanceof Integer) {
|
xposedminversion = (Integer) minVersionRaw;
|
||||||
xposedminversion = (Integer) minVersionRaw;
|
} else if (minVersionRaw instanceof String) {
|
||||||
} else if (minVersionRaw instanceof String) {
|
xposedminversion = MetaDataReader.extractIntPart((String) minVersionRaw);
|
||||||
xposedminversion = MetaDataReader.extractIntPart((String) minVersionRaw);
|
|
||||||
}
|
|
||||||
xposedsharedprefs = metaData.containsKey("xposedsharedprefs");
|
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException | IOException e) {
|
xposedsharedprefs = metaData.containsKey("xposedsharedprefs");
|
||||||
Log.w(TAG, "Apk parser fails: " + e);
|
|
||||||
}
|
}
|
||||||
newModule = isModule && (xposedminversion > 92 || xposedsharedprefs);
|
} catch (NumberFormatException | IOException e) {
|
||||||
|
Log.w(TAG, "Apk parser fails: " + e);
|
||||||
}
|
}
|
||||||
|
newModule = isModule && (xposedminversion > 92 || xposedsharedprefs);
|
||||||
}
|
}
|
||||||
if (newModule) {
|
if (newModule) {
|
||||||
mFile = new File(serviceClient.getPrefsPath(packageName), prefFileName + ".xml");
|
mFile = new File(serviceClient.getPrefsPath(packageName), prefFileName + ".xml");
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import static de.robv.android.xposed.XposedHelpers.getObjectField;
|
||||||
import static de.robv.android.xposed.XposedHelpers.getParameterIndexByType;
|
import static de.robv.android.xposed.XposedHelpers.getParameterIndexByType;
|
||||||
import static de.robv.android.xposed.XposedHelpers.setStaticObjectField;
|
import static de.robv.android.xposed.XposedHelpers.setStaticObjectField;
|
||||||
|
|
||||||
|
import android.app.ActivityThread;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.content.res.ResourcesImpl;
|
import android.content.res.ResourcesImpl;
|
||||||
|
|
@ -50,9 +51,10 @@ import java.lang.ref.WeakReference;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import de.robv.android.xposed.callbacks.XC_InitPackageResources;
|
import de.robv.android.xposed.callbacks.XC_InitPackageResources;
|
||||||
|
|
@ -82,7 +84,7 @@ public final class XposedInit {
|
||||||
findAndHookMethod("android.app.ApplicationPackageManager", null, "getResourcesForApplication",
|
findAndHookMethod("android.app.ApplicationPackageManager", null, "getResourcesForApplication",
|
||||||
ApplicationInfo.class, new XC_MethodHook() {
|
ApplicationInfo.class, new XC_MethodHook() {
|
||||||
@Override
|
@Override
|
||||||
protected void beforeHookedMethod(MethodHookParam param) {
|
protected void beforeHookedMethod(MethodHookParam<?> param) {
|
||||||
ApplicationInfo app = (ApplicationInfo) param.args[0];
|
ApplicationInfo app = (ApplicationInfo) param.args[0];
|
||||||
XResources.setPackageNameForResDir(app.packageName,
|
XResources.setPackageNameForResDir(app.packageName,
|
||||||
app.uid == Process.myUid() ? app.sourceDir : app.publicSourceDir);
|
app.uid == Process.myUid() ? app.sourceDir : app.publicSourceDir);
|
||||||
|
|
@ -117,7 +119,7 @@ public final class XposedInit {
|
||||||
final Class<?> classActivityRes = XposedHelpers.findClassIfExists("android.app.ResourcesManager$ActivityResource", classGTLR.getClassLoader());
|
final Class<?> classActivityRes = XposedHelpers.findClassIfExists("android.app.ResourcesManager$ActivityResource", classGTLR.getClassLoader());
|
||||||
var hooker = new XC_MethodHook() {
|
var hooker = new XC_MethodHook() {
|
||||||
@Override
|
@Override
|
||||||
protected void afterHookedMethod(MethodHookParam param) {
|
protected void afterHookedMethod(MethodHookParam<?> param) {
|
||||||
// At least on OnePlus 5, the method has an additional parameter compared to AOSP.
|
// At least on OnePlus 5, the method has an additional parameter compared to AOSP.
|
||||||
Object activityToken = null;
|
Object activityToken = null;
|
||||||
try {
|
try {
|
||||||
|
|
@ -162,7 +164,7 @@ public final class XposedInit {
|
||||||
findAndHookMethod(TypedArray.class, "obtain", Resources.class, int.class,
|
findAndHookMethod(TypedArray.class, "obtain", Resources.class, int.class,
|
||||||
new XC_MethodHook() {
|
new XC_MethodHook() {
|
||||||
@Override
|
@Override
|
||||||
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
protected void afterHookedMethod(MethodHookParam<?> param) throws Throwable {
|
||||||
if (param.getResult() instanceof XResources.XTypedArray) {
|
if (param.getResult() instanceof XResources.XTypedArray) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -189,7 +191,7 @@ public final class XposedInit {
|
||||||
XResources.init(latestResKey);
|
XResources.init(latestResKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static XResources cloneToXResources(XC_MethodHook.MethodHookParam param, String resDir) {
|
private static XResources cloneToXResources(XC_MethodHook.MethodHookParam<?> param, String resDir) {
|
||||||
Object result = param.getResult();
|
Object result = param.getResult();
|
||||||
if (result == null || result instanceof XResources) {
|
if (result == null || result instanceof XResources) {
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -213,21 +215,31 @@ public final class XposedInit {
|
||||||
return newRes;
|
return newRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Set<String> loadedModules = new CopyOnWriteArraySet<>();
|
// only legacy modules have non-empty value
|
||||||
|
private static final Map<String, Optional<String>> loadedModules = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public static Set<String> getLoadedModules() {
|
public static Map<String, Optional<String>> getLoadedModules() {
|
||||||
return loadedModules;
|
return loadedModules;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadModules() {
|
public static void loadLegacyModules() {
|
||||||
var moduleList = serviceClient.getLegacyModulesList();
|
var moduleList = serviceClient.getLegacyModulesList();
|
||||||
moduleList.forEach(module -> {
|
moduleList.forEach(module -> {
|
||||||
var apk = module.apkPath;
|
var apk = module.apkPath;
|
||||||
var name = module.packageName;
|
var name = module.packageName;
|
||||||
var file = module.file;
|
var file = module.file;
|
||||||
loadedModules.add(apk); // temporarily add it for XSharedPreference
|
loadedModules.put(name, Optional.of(apk)); // temporarily add it for XSharedPreference
|
||||||
if (!loadModule(name, apk, file)) {
|
if (!loadModule(name, apk, file)) {
|
||||||
loadedModules.remove(apk);
|
loadedModules.remove(name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void loadModules(ActivityThread at) {
|
||||||
|
serviceClient.getModulesList().forEach(module -> {
|
||||||
|
loadedModules.put(module.packageName, Optional.empty());
|
||||||
|
if (!LSPosedContext.loadModule(at, module)) {
|
||||||
|
loadedModules.remove(module.packageName);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ public class Startup {
|
||||||
// Initialize the Xposed framework
|
// Initialize the Xposed framework
|
||||||
try {
|
try {
|
||||||
startBootstrapHook(XposedInit.startsSystemServer);
|
startBootstrapHook(XposedInit.startsSystemServer);
|
||||||
XposedInit.loadModules();
|
XposedInit.loadLegacyModules();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Utils.logE("error during Xposed initialization", t);
|
Utils.logE("error during Xposed initialization", t);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,14 @@ import android.app.ActivityThread;
|
||||||
|
|
||||||
import org.lsposed.lspd.impl.LSPosedContext;
|
import org.lsposed.lspd.impl.LSPosedContext;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import de.robv.android.xposed.XC_MethodHook;
|
import de.robv.android.xposed.XC_MethodHook;
|
||||||
import de.robv.android.xposed.XposedInit;
|
import de.robv.android.xposed.XposedInit;
|
||||||
|
|
||||||
public class AttachHooker extends XC_MethodHook {
|
public class AttachHooker extends XC_MethodHook {
|
||||||
@Override
|
@Override
|
||||||
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
protected void afterHookedMethod(MethodHookParam<?> param) throws Throwable {
|
||||||
serviceClient.getModulesList().forEach(module -> {
|
XposedInit.loadModules((ActivityThread) param.thisObject);
|
||||||
if (LSPosedContext.loadModule((ActivityThread) param.thisObject, module)) {
|
|
||||||
XposedInit.getLoadedModules().add(module.packageName);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import de.robv.android.xposed.XposedBridge;
|
||||||
|
|
||||||
public class CrashDumpHooker extends XC_MethodHook {
|
public class CrashDumpHooker extends XC_MethodHook {
|
||||||
@Override
|
@Override
|
||||||
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
|
protected void beforeHookedMethod(MethodHookParam<?> param) {
|
||||||
try {
|
try {
|
||||||
var e = (Throwable) param.args[0];
|
var e = (Throwable) param.args[0];
|
||||||
XposedBridge.log("Crash unexpectedly: " + Log.getStackTraceString(e));
|
XposedBridge.log("Crash unexpectedly: " + Log.getStackTraceString(e));
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ public class HandleSystemServerProcessHooker extends XC_MethodHook {
|
||||||
public static volatile ClassLoader systemServerCL;
|
public static volatile ClassLoader systemServerCL;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void afterHookedMethod(MethodHookParam param) {
|
protected void afterHookedMethod(MethodHookParam<?> param) {
|
||||||
Hookers.logD("ZygoteInit#handleSystemServerProcess() starts");
|
Hookers.logD("ZygoteInit#handleSystemServerProcess() starts");
|
||||||
try {
|
try {
|
||||||
// get system_server classLoader
|
// get system_server classLoader
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,15 @@
|
||||||
|
|
||||||
package org.lsposed.lspd.hooker;
|
package org.lsposed.lspd.hooker;
|
||||||
|
|
||||||
|
import android.app.ActivityThread;
|
||||||
import android.app.LoadedApk;
|
import android.app.LoadedApk;
|
||||||
import android.content.res.XResources;
|
import android.content.res.XResources;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.lsposed.lspd.util.Hookers;
|
import org.lsposed.lspd.util.Hookers;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import de.robv.android.xposed.XC_MethodHook;
|
import de.robv.android.xposed.XC_MethodHook;
|
||||||
import de.robv.android.xposed.XposedHelpers;
|
import de.robv.android.xposed.XposedHelpers;
|
||||||
import de.robv.android.xposed.XposedInit;
|
import de.robv.android.xposed.XposedInit;
|
||||||
|
|
@ -34,13 +37,14 @@ import de.robv.android.xposed.XposedInit;
|
||||||
public class LoadedApkCtorHooker extends XC_MethodHook {
|
public class LoadedApkCtorHooker extends XC_MethodHook {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void afterHookedMethod(MethodHookParam param) {
|
protected void afterHookedMethod(MethodHookParam<?> param) {
|
||||||
Hookers.logD("LoadedApk#<init> starts");
|
Hookers.logD("LoadedApk#<init> starts");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
LoadedApk loadedApk = (LoadedApk) param.thisObject;
|
LoadedApk loadedApk = (LoadedApk) param.thisObject;
|
||||||
String packageName = loadedApk.getPackageName();
|
String packageName = loadedApk.getPackageName();
|
||||||
if (XposedInit.getLoadedModules().contains(packageName)) {
|
boolean isFirstPackage = packageName != null && ActivityThread.currentProcessName() != null && packageName.equals(ActivityThread.currentPackageName());
|
||||||
|
if (!isFirstPackage && !XposedInit.getLoadedModules().getOrDefault(packageName, Optional.of("")).isPresent()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Object mAppDir = XposedHelpers.getObjectField(loadedApk, "mAppDir");
|
Object mAppDir = XposedHelpers.getObjectField(loadedApk, "mAppDir");
|
||||||
|
|
@ -77,7 +81,7 @@ public class LoadedApkCtorHooker extends XC_MethodHook {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
new LoadedApkGetCLHooker(loadedApk);
|
new LoadedApkGetCLHooker(loadedApk, isFirstPackage);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Hookers.logE("error when hooking LoadedApk.<init>", t);
|
Hookers.logE("error when hooking LoadedApk.<init>", t);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,13 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import de.robv.android.xposed.XC_MethodHook;
|
import de.robv.android.xposed.XC_MethodHook;
|
||||||
import de.robv.android.xposed.XC_MethodReplacement;
|
import de.robv.android.xposed.XC_MethodReplacement;
|
||||||
import de.robv.android.xposed.XposedBridge;
|
import de.robv.android.xposed.XposedBridge;
|
||||||
import de.robv.android.xposed.XposedHelpers;
|
import de.robv.android.xposed.XposedHelpers;
|
||||||
|
import de.robv.android.xposed.XposedInit;
|
||||||
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
||||||
import io.github.libxposed.api.XposedModuleInterface;
|
import io.github.libxposed.api.XposedModuleInterface;
|
||||||
|
|
||||||
|
|
@ -67,13 +69,16 @@ public class LoadedApkGetCLHooker extends XC_MethodHook {
|
||||||
private final LoadedApk loadedApk;
|
private final LoadedApk loadedApk;
|
||||||
private final Unhook unhook;
|
private final Unhook unhook;
|
||||||
|
|
||||||
public LoadedApkGetCLHooker(LoadedApk loadedApk) {
|
private final boolean isFirstPackage;
|
||||||
|
|
||||||
|
public LoadedApkGetCLHooker(LoadedApk loadedApk, boolean isFirstPackage) {
|
||||||
this.loadedApk = loadedApk;
|
this.loadedApk = loadedApk;
|
||||||
|
this.isFirstPackage = isFirstPackage;
|
||||||
unhook = XposedHelpers.findAndHookMethod(LoadedApk.class, "getClassLoader", this);
|
unhook = XposedHelpers.findAndHookMethod(LoadedApk.class, "getClassLoader", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void afterHookedMethod(MethodHookParam param) {
|
protected void afterHookedMethod(MethodHookParam<?> param) {
|
||||||
LoadedApk loadedApk = (LoadedApk) param.thisObject;
|
LoadedApk loadedApk = (LoadedApk) param.thisObject;
|
||||||
|
|
||||||
if (loadedApk != this.loadedApk) {
|
if (loadedApk != this.loadedApk) {
|
||||||
|
|
@ -83,15 +88,8 @@ public class LoadedApkGetCLHooker extends XC_MethodHook {
|
||||||
try {
|
try {
|
||||||
Hookers.logD("LoadedApk#getClassLoader starts");
|
Hookers.logD("LoadedApk#getClassLoader starts");
|
||||||
|
|
||||||
String packageName = ActivityThread.currentPackageName();
|
final String processName = AndroidAppHelper.currentProcessName();
|
||||||
String processName = ActivityThread.currentProcessName();
|
final String packageName = isFirstPackage && "android".equals(ActivityThread.currentPackageName()) ? "system" : loadedApk.getPackageName();
|
||||||
boolean isFirstPackage = packageName != null && processName != null && packageName.equals(loadedApk.getPackageName());
|
|
||||||
if (!isFirstPackage) {
|
|
||||||
packageName = loadedApk.getPackageName();
|
|
||||||
processName = AndroidAppHelper.currentProcessName();
|
|
||||||
} else if (packageName.equals("android")) {
|
|
||||||
packageName = "system";
|
|
||||||
}
|
|
||||||
|
|
||||||
Object mAppDir = XposedHelpers.getObjectField(loadedApk, "mAppDir");
|
Object mAppDir = XposedHelpers.getObjectField(loadedApk, "mAppDir");
|
||||||
ClassLoader classLoader = (ClassLoader) param.getResult();
|
ClassLoader classLoader = (ClassLoader) param.getResult();
|
||||||
|
|
@ -109,7 +107,9 @@ public class LoadedApkGetCLHooker extends XC_MethodHook {
|
||||||
lpparam.appInfo = loadedApk.getApplicationInfo();
|
lpparam.appInfo = loadedApk.getApplicationInfo();
|
||||||
lpparam.isFirstApplication = isFirstPackage;
|
lpparam.isFirstApplication = isFirstPackage;
|
||||||
|
|
||||||
hookNewXSP(lpparam);
|
if (isFirstPackage && XposedInit.getLoadedModules().getOrDefault(packageName, Optional.empty()).isPresent()) {
|
||||||
|
hookNewXSP(lpparam);
|
||||||
|
}
|
||||||
|
|
||||||
Hookers.logD("Call handleLoadedPackage: packageName=" + lpparam.packageName + " processName=" + lpparam.processName + " isFirstPackage=" + isFirstPackage + " classLoader=" + lpparam.classLoader + " appInfo=" + lpparam.appInfo);
|
Hookers.logD("Call handleLoadedPackage: packageName=" + lpparam.packageName + " processName=" + lpparam.processName + " isFirstPackage=" + isFirstPackage + " classLoader=" + lpparam.classLoader + " appInfo=" + lpparam.appInfo);
|
||||||
XC_LoadPackage.callAll(lpparam);
|
XC_LoadPackage.callAll(lpparam);
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import de.robv.android.xposed.XposedHelpers;
|
||||||
|
|
||||||
public class OpenDexFileHooker extends XC_MethodHook {
|
public class OpenDexFileHooker extends XC_MethodHook {
|
||||||
@Override
|
@Override
|
||||||
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
protected void afterHookedMethod(MethodHookParam<?> param) throws Throwable {
|
||||||
ClassLoader classLoader = null;
|
ClassLoader classLoader = null;
|
||||||
for (var arg : param.args) {
|
for (var arg : param.args) {
|
||||||
if (arg instanceof ClassLoader) {
|
if (arg instanceof ClassLoader) {
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ import io.github.libxposed.api.XposedModuleInterface;
|
||||||
public class StartBootstrapServicesHooker extends XC_MethodHook {
|
public class StartBootstrapServicesHooker extends XC_MethodHook {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void beforeHookedMethod(MethodHookParam param) {
|
protected void beforeHookedMethod(MethodHookParam<?> param) {
|
||||||
logD("SystemServer#startBootstrapServices() starts");
|
logD("SystemServer#startBootstrapServices() starts");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ public class ConfigManager {
|
||||||
private boolean verboseLog = true;
|
private boolean verboseLog = true;
|
||||||
private boolean dexObfuscate = false;
|
private boolean dexObfuscate = false;
|
||||||
private boolean enableStatusNotification = true;
|
private boolean enableStatusNotification = true;
|
||||||
private String miscPath = null;
|
private Path miscPath = null;
|
||||||
|
|
||||||
private int managerUid = -1;
|
private int managerUid = -1;
|
||||||
|
|
||||||
|
|
@ -280,16 +280,15 @@ public class ConfigManager {
|
||||||
// Don't migrate to ConfigFileManager, as XSharedPreferences will be restored soon
|
// Don't migrate to ConfigFileManager, as XSharedPreferences will be restored soon
|
||||||
String string = (String) config.get("misc_path");
|
String string = (String) config.get("misc_path");
|
||||||
if (string == null) {
|
if (string == null) {
|
||||||
miscPath = "/data/misc/" + UUID.randomUUID().toString();
|
miscPath = Paths.get("/data", "misc", UUID.randomUUID().toString());
|
||||||
updateModulePrefs("lspd", 0, "config", "misc_path", miscPath);
|
updateModulePrefs("lspd", 0, "config", "misc_path", miscPath.toString());
|
||||||
} else {
|
} else {
|
||||||
miscPath = string;
|
miscPath = Paths.get(string);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Path prefs = Paths.get(miscPath);
|
|
||||||
var perms = PosixFilePermissions.fromString("rwx--x--x");
|
var perms = PosixFilePermissions.fromString("rwx--x--x");
|
||||||
Files.createDirectories(prefs, PosixFilePermissions.asFileAttribute(perms));
|
Files.createDirectories(miscPath, PosixFilePermissions.asFileAttribute(perms));
|
||||||
walkFileTree(prefs, f -> SELinux.setFileContext(f.toString(), "u:object_r:magisk_file:s0"));
|
walkFileTree(miscPath, f -> SELinux.setFileContext(f.toString(), "u:object_r:magisk_file:s0"));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, Log.getStackTraceString(e));
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
}
|
}
|
||||||
|
|
@ -1083,9 +1082,26 @@ public class ConfigManager {
|
||||||
return managerUid != -1;
|
return managerUid != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPrefsPath(String fileName, int uid) {
|
public String getPrefsPath(String packageName, int uid) {
|
||||||
int userId = uid / PER_USER_RANGE;
|
int userId = uid / PER_USER_RANGE;
|
||||||
return miscPath + "/prefs" + (userId == 0 ? "" : String.valueOf(userId)) + "/" + fileName;
|
var path = miscPath.resolve("prefs" + (userId == 0 ? "" : String.valueOf(userId))).resolve(packageName);
|
||||||
|
var module = cachedModule.getOrDefault(packageName, null);
|
||||||
|
if (module != null && module.appId == uid % PER_USER_RANGE) {
|
||||||
|
try {
|
||||||
|
var perms = PosixFilePermissions.fromString("rwx--x--x");
|
||||||
|
Files.createDirectories(path, PosixFilePermissions.asFileAttribute(perms));
|
||||||
|
walkFileTree(path, p -> {
|
||||||
|
try {
|
||||||
|
Os.chown(p.toString(), uid, uid);
|
||||||
|
} catch (ErrnoException e) {
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is slow, avoid using it
|
// this is slow, avoid using it
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue