From 9d417fa6cfa868c5fca155c196773fe2d73bdbe6 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Fri, 21 May 2021 05:10:09 +0800 Subject: [PATCH] Load module together with package name --- .../lspd/service/ILSPApplicationService.aidl | 2 +- .../de/robv/android/xposed/XposedInit.java | 32 ++++++++-------- .../config/LSPApplicationServiceClient.java | 9 +++-- .../lsposed/lspd/service/ConfigManager.java | 37 ++++++++++--------- .../lspd/service/LSPApplicationService.java | 6 +-- 5 files changed, 46 insertions(+), 40 deletions(-) diff --git a/core/src/main/aidl/org/lsposed/lspd/service/ILSPApplicationService.aidl b/core/src/main/aidl/org/lsposed/lspd/service/ILSPApplicationService.aidl index a06d2613..62bcbe7d 100644 --- a/core/src/main/aidl/org/lsposed/lspd/service/ILSPApplicationService.aidl +++ b/core/src/main/aidl/org/lsposed/lspd/service/ILSPApplicationService.aidl @@ -7,7 +7,7 @@ interface ILSPApplicationService { boolean isResourcesHookEnabled() = 5; - String[] getModulesList(String processName) = 6; + Map getModulesList(String processName) = 6; String getPrefsPath(String packageName) = 7; diff --git a/core/src/main/java/de/robv/android/xposed/XposedInit.java b/core/src/main/java/de/robv/android/xposed/XposedInit.java index 88ad0527..32573f03 100644 --- a/core/src/main/java/de/robv/android/xposed/XposedInit.java +++ b/core/src/main/java/de/robv/android/xposed/XposedInit.java @@ -219,25 +219,25 @@ public final class XposedInit { return false; } synchronized (moduleLoadLock) { - // TODO: process name - String[] moduleList = serviceClient.getModulesList(); + var moduleList = serviceClient.getModulesList(); ArraySet newLoadedApk = new ArraySet<>(); - for (String apk : moduleList) + moduleList.forEach((name, apk) -> { if (loadedModules.contains(apk)) { newLoadedApk.add(apk); } else { loadedModules.add(apk); // temporarily add it for XSharedPreference - boolean loadSuccess = loadModule(apk); + boolean loadSuccess = loadModule(name, apk); if (loadSuccess) { newLoadedApk.add(apk); } } - loadedModules.clear(); - loadedModules.addAll(newLoadedApk); + loadedModules.clear(); + loadedModules.addAll(newLoadedApk); - // refresh callback according to current loaded module list - pruneCallbacks(loadedModules); + // refresh callback according to current loaded module list + pruneCallbacks(loadedModules); + }); } return true; } @@ -276,7 +276,7 @@ public final class XposedInit { * Load all so from an APK by reading assets/native_init. * It will only store the so names but not doing anything. */ - private static boolean initNativeModule(ClassLoader mcl, String apk) { + private static boolean initNativeModule(ClassLoader mcl, String name) { InputStream is = mcl.getResourceAsStream("assets/native_init"); if (is == null) return true; BufferedReader moduleLibraryReader = new BufferedReader(new InputStreamReader(is)); @@ -288,7 +288,7 @@ public final class XposedInit { } } } catch (IOException e) { - Log.e(TAG, " Failed to load native library list from " + apk, e); + Log.e(TAG, " Failed to load native library list from " + name, e); return false; } finally { closeSilently(is); @@ -297,7 +297,7 @@ public final class XposedInit { } - private static boolean initModule(ClassLoader mcl, String apk) { + private static boolean initModule(ClassLoader mcl, String name, String apk) { InputStream is = mcl.getResourceAsStream("assets/xposed_init"); if (is == null) { return true; @@ -346,7 +346,7 @@ public final class XposedInit { } } } catch (IOException e) { - Log.e(TAG, " Failed to load module from " + apk, e); + Log.e(TAG, " Failed to load module " + name + " from " + apk, e); return false; } finally { closeSilently(is); @@ -359,8 +359,8 @@ public final class XposedInit { * in assets/xposed_init. */ @SuppressLint("PrivateApi") - private static boolean loadModule(String apk) { - Log.i(TAG, "Loading modules from " + apk); + private static boolean loadModule(String name, String apk) { + Log.i(TAG, "Loading module " + name + " from " + apk); if (!new File(apk).exists()) { Log.e(TAG, " File does not exist"); @@ -378,7 +378,7 @@ public final class XposedInit { try { if (mcl.loadClass(XposedBridge.class.getName()).getClassLoader() != initLoader) { - Log.e(TAG, " Cannot load module:"); + Log.e(TAG, " Cannot load module: " + name); Log.e(TAG, " The Xposed API classes are compiled into the module's APK."); Log.e(TAG, " This may cause strange issues and must be fixed by the module developer."); Log.e(TAG, " For details, see: http://api.xposed.info/using.html"); @@ -387,7 +387,7 @@ public final class XposedInit { } catch (ClassNotFoundException ignored) { } - return initNativeModule(mcl, apk) && initModule(mcl, apk); + return initNativeModule(mcl, apk) && initModule(mcl, name, apk); } public final static HashSet loadedPackagesInProcess = new HashSet<>(1); diff --git a/core/src/main/java/org/lsposed/lspd/config/LSPApplicationServiceClient.java b/core/src/main/java/org/lsposed/lspd/config/LSPApplicationServiceClient.java index 2b239c80..b9010605 100644 --- a/core/src/main/java/org/lsposed/lspd/config/LSPApplicationServiceClient.java +++ b/core/src/main/java/org/lsposed/lspd/config/LSPApplicationServiceClient.java @@ -24,6 +24,8 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import java.io.File; +import java.util.Collections; +import java.util.Map; import org.lsposed.lspd.service.ILSPApplicationService; import org.lsposed.lspd.util.Utils; @@ -86,15 +88,16 @@ public class LSPApplicationServiceClient implements ILSPApplicationService { } @Override - public String[] getModulesList(String processName) { + public Map getModulesList(String processName) { try { + //noinspection unchecked return service.getModulesList(processName); } catch (RemoteException | NullPointerException ignored) { } - return new String[0]; + return Collections.emptyMap(); } - public String[] getModulesList() { + public Map getModulesList() { return getModulesList(processName); } diff --git a/core/src/main/java/org/lsposed/lspd/service/ConfigManager.java b/core/src/main/java/org/lsposed/lspd/service/ConfigManager.java index afac5e03..3005da12 100644 --- a/core/src/main/java/org/lsposed/lspd/service/ConfigManager.java +++ b/core/src/main/java/org/lsposed/lspd/service/ConfigManager.java @@ -113,7 +113,7 @@ public class ConfigManager { private final Handler cacheHandler; - private final ConcurrentHashMap moduleDexes = new ConcurrentHashMap<>(); + private final Map moduleDexes = new ConcurrentHashMap<>(); private long lastModuleCacheTime = 0; private long requestModuleCacheTime = 0; @@ -161,9 +161,9 @@ public class ConfigManager { "PRIMARY KEY (mid, app_pkg_name, user_id)" + ");"); - private final ConcurrentHashMap> cachedScope = new ConcurrentHashMap<>(); + private final Map> cachedScope = new ConcurrentHashMap<>(); - private final ConcurrentHashMap cachedModule = new ConcurrentHashMap<>(); + private final Map cachedModule = new ConcurrentHashMap<>(); private void updateCaches(boolean sync) { synchronized (this) { @@ -206,15 +206,16 @@ public class ConfigManager { } } - public String[] getModulesPathForSystemServer() { - HashSet modules = new HashSet<>(); - try (Cursor cursor = db.query("scope INNER JOIN modules ON scope.mid = modules.mid", new String[]{"apk_path"}, "app_pkg_name=? AND enabled=1", new String[]{"android"}, null, null, null)) { + public Map getModulesForSystemServer() { + HashMap modules = new HashMap<>(); + try (Cursor cursor = db.query("scope INNER JOIN modules ON scope.mid = modules.mid", new String[]{"module_pkg_name", "apk_path"}, "app_pkg_name=? AND enabled=1", new String[]{"android"}, null, null, null)) { int apkPathIdx = cursor.getColumnIndex("apk_path"); + int pkgNameIdx = cursor.getColumnIndex("module_pkg_name"); while (cursor.moveToNext()) { - modules.add(cursor.getString(apkPathIdx)); + modules.put(cursor.getString(pkgNameIdx), cursor.getString(apkPathIdx)); } } - return modules.toArray(new String[0]); + return modules; } private static String readText(@NonNull File file) throws IOException { @@ -388,13 +389,14 @@ public class ConfigManager { if (lastScopeCacheTime >= requestScopeCacheTime) return; else lastScopeCacheTime = SystemClock.elapsedRealtime(); cachedScope.clear(); - try (Cursor cursor = db.query("scope INNER JOIN modules ON scope.mid = modules.mid", new String[]{"app_pkg_name", "user_id", "apk_path"}, + try (Cursor cursor = db.query("scope INNER JOIN modules ON scope.mid = modules.mid", new String[]{"app_pkg_name", "module_pkg_name", "user_id", "apk_path"}, "enabled = 1", null, null, null, null)) { if (cursor == null) { Log.e(TAG, "db cache failed"); return; } int appPkgNameIdx = cursor.getColumnIndex("app_pkg_name"); + int modulePkgNameIdx = cursor.getColumnIndex("module_pkg_name"); int userIdIdx = cursor.getColumnIndex("user_id"); int apkPathIdx = cursor.getColumnIndex("apk_path"); HashSet obsoletePackages = new HashSet<>(); @@ -405,6 +407,7 @@ public class ConfigManager { // system server always loads database if (app.packageName.equals("android")) continue; String apk_path = cursor.getString(apkPathIdx); + String module_pkg = cursor.getString(modulePkgNameIdx); try { List processesScope = getAssociatedProcesses(app); if (processesScope.isEmpty()) { @@ -412,7 +415,7 @@ public class ConfigManager { continue; } for (ProcessScope processScope : processesScope) - cachedScope.computeIfAbsent(processScope, ignored -> new HashSet<>()).add(apk_path); + cachedScope.computeIfAbsent(processScope, ignored -> new HashMap<>()).put(module_pkg, apk_path); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(e)); } @@ -423,17 +426,17 @@ public class ConfigManager { } } Log.d(TAG, "cached Scope"); - for (ProcessScope ps : cachedScope.keySet()) { + cachedScope.forEach((ps, module) -> { Log.d(TAG, ps.processName + "/" + ps.uid); - for (String apk : cachedScope.get(ps)) { - Log.d(TAG, "\t" + apk); - } - } + module.forEach((pkg_name, apk_path) -> { + Log.d(TAG, "\t" + pkg_name); + }); + }); } // This is called when a new process created, use the cached result - public String[] getModulesPathForProcess(String processName, int uid) { - return isManager(uid) ? new String[0] : cachedScope.getOrDefault(new ProcessScope(processName, uid), Collections.emptySet()).toArray(new String[0]); + public Map getModulesForProcess(String processName, int uid) { + return isManager(uid) ? Collections.emptyMap() : cachedScope.getOrDefault(new ProcessScope(processName, uid), Collections.emptyMap()); } // This is called when a new process created, use the cached result diff --git a/core/src/main/java/org/lsposed/lspd/service/LSPApplicationService.java b/core/src/main/java/org/lsposed/lspd/service/LSPApplicationService.java index 7ae76872..e03cea52 100644 --- a/core/src/main/java/org/lsposed/lspd/service/LSPApplicationService.java +++ b/core/src/main/java/org/lsposed/lspd/service/LSPApplicationService.java @@ -67,13 +67,13 @@ public class LSPApplicationService extends ILSPApplicationService.Stub { } @Override - public String[] getModulesList(String processName) throws RemoteException { + public Map getModulesList(String processName) throws RemoteException { ensureRegistered(); int callingUid = getCallingUid(); if (callingUid == 1000 && processName.equals("android")) { - return ConfigManager.getInstance().getModulesPathForSystemServer(); + return ConfigManager.getInstance().getModulesForSystemServer(); } - return ConfigManager.getInstance().getModulesPathForProcess(processName, callingUid); + return ConfigManager.getInstance().getModulesForProcess(processName, callingUid); } @Override