From 56504a5f3b72c2b72d9b648dd2dd62d7596bf4c7 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Sat, 20 Feb 2021 03:30:17 +0800 Subject: [PATCH] [core] Fix caching logic --- .../lsposed/lspd/service/ConfigManager.java | 60 +++++++++---------- .../lspd/service/LSPApplicationService.java | 2 +- .../lsposed/lspd/service/LSPosedService.java | 2 +- .../lsposed/lspd/service/PackageService.java | 23 ++++--- 4 files changed, 42 insertions(+), 45 deletions(-) diff --git a/core/src/main/java/io/github/lsposed/lspd/service/ConfigManager.java b/core/src/main/java/io/github/lsposed/lspd/service/ConfigManager.java index b2b55d35..50717066 100644 --- a/core/src/main/java/io/github/lsposed/lspd/service/ConfigManager.java +++ b/core/src/main/java/io/github/lsposed/lspd/service/ConfigManager.java @@ -9,6 +9,7 @@ import android.os.FileObserver; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Log; +import android.util.Pair; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -40,6 +41,8 @@ public class ConfigManager { static final private File configPath = new File(basePath, "config"); static final private SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(new File(configPath, "modules_config.db"), null); + boolean packageStarted = false; + static final private File resourceHookSwitch = new File(configPath, "enable_resources"); private boolean resourceHook = false; @@ -114,15 +117,16 @@ public class ConfigManager { private final ConcurrentHashMap> cachedScope = new ConcurrentHashMap<>(); - public static boolean shouldSkipSystemServer() { - try (Cursor cursor = db.query("scope", new String[]{"mid"}, "app_pkg_name=?", new String[]{"android"}, null, null, null)) { + // for system server, cache is not yet ready, we need to query database for it + public boolean shouldSkipSystemServer() { + try (Cursor cursor = db.query("scope INNER JOIN modules ON scope.mid = modules.mid", new String[]{"modules.mid"}, "app_pkg_name=? AND enabled=1", new String[]{"android"}, null, null, null)) { return cursor == null || !cursor.moveToNext(); } } - public static String[] getModulesPathForSystemServer() { + 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=?", new String[]{"android"}, null, null, null)) { + 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)) { int apkPathIdx = cursor.getColumnIndex("apk_path"); while (cursor.moveToNext()) { modules.add(cursor.getString(apkPathIdx)); @@ -176,6 +180,7 @@ public class ConfigManager { } public synchronized void updateManager() { + if (!packageStarted) return; try { PackageInfo info = PackageService.getPackageInfo(readText(managerPath, DEFAULT_MANAGER_PACKAGE_NAME), 0, 0); if (info != null) { @@ -195,6 +200,14 @@ public class ConfigManager { static ConfigManager getInstance() { if (instance == null) instance = new ConfigManager(); + if (!instance.packageStarted) { + if (PackageService.getPackageManager() != null) { + Log.d(TAG, "pm is ready, updating cache"); + instance.packageStarted = true; + instance.cacheScopes(); + instance.updateManager(); + } + } return instance; } @@ -212,20 +225,20 @@ public class ConfigManager { } private List getAssociatedProcesses(Application app) throws RemoteException { - PackageInfo pkgInfo = PackageService.getPackageInfo(app.packageName, 0, app.userId); + Pair, Integer> result = PackageService.fetchProcessesWithUid(app); List processes = new ArrayList<>(); - if (pkgInfo != null && pkgInfo.applicationInfo != null) { - for (String process : PackageService.getProcessesForUid(pkgInfo.applicationInfo.uid, app.userId)) { - processes.add(new ProcessScope(process, pkgInfo.applicationInfo.uid)); - } + for (String processName : result.first) { + processes.add(new ProcessScope(processName, result.second)); } return processes; } private synchronized void cacheScopes() { + // skip caching when pm is not yet available + if (!packageStarted) return; 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"}, - "enabled = ?", new String[]{"1"}, null, null, null)) { + "enabled = 1", null, null, null, null)) { if (cursor == null) { Log.e(TAG, "db cache failed"); return; @@ -238,6 +251,8 @@ public class ConfigManager { Application app = new Application(); app.packageName = cursor.getString(appPkgNameIdx); app.userId = cursor.getInt(userIdIdx); + // system server always loads database + if (app.packageName.equals("android")) continue; String apk_path = cursor.getString(apkPathIdx); try { List processesScope = getAssociatedProcesses(app); @@ -253,13 +268,13 @@ public class ConfigManager { } for (Application obsoletePackage : obsoletePackages) { Log.d(TAG, "removing obsolete package: " + obsoletePackage.packageName + "/" + obsoletePackage.userId); - removeAppWithoutCache(obsoletePackage); + removeApp(obsoletePackage); } } Log.d(TAG, "cached Scope"); - for(ProcessScope ps : cachedScope.keySet()) { + for (ProcessScope ps : cachedScope.keySet()) { Log.d(TAG, ps.processName + "/" + ps.uid); - for(String apk: cachedScope.get(ps)) { + for (String apk : cachedScope.get(ps)) { Log.d(TAG, "\t" + apk); } } @@ -309,9 +324,6 @@ public class ConfigManager { if (count < 0) { count = db.updateWithOnConflict("modules", values, "module_pkg_name=?", new String[]{packageName}, SQLiteDatabase.CONFLICT_IGNORE); } - if (count >= 1) { - cacheScopes(); - } return count >= 0; } @@ -351,12 +363,11 @@ public class ConfigManager { db.setTransactionSuccessful(); db.endTransaction(); } - cacheScopes(); return true; } public String[] enabledModules() { - try (Cursor cursor = db.query("modules", new String[]{"module_pkg_name"}, "enabled = ?", new String[]{"1"}, null, null, null)) { + try (Cursor cursor = db.query("modules", new String[]{"module_pkg_name"}, "enabled = 1", null, null, null, null)) { if (cursor == null) { Log.e(TAG, "query enabled modules failed"); return null; @@ -381,7 +392,6 @@ public class ConfigManager { db.setTransactionSuccessful(); db.endTransaction(); } - cacheScopes(); return true; } @@ -397,7 +407,6 @@ public class ConfigManager { db.setTransactionSuccessful(); db.endTransaction(); } - cacheScopes(); return true; } @@ -414,23 +423,14 @@ public class ConfigManager { db.setTransactionSuccessful(); db.endTransaction(); } - cacheScopes(); return true; } - public boolean removeAppWithoutCache(Application app) { + public boolean removeApp(Application app) { int count = db.delete("scope", "app_pkg_name = ? AND user_id=?", new String[]{app.packageName, String.valueOf(app.userId)}); return count >= 1; } - public boolean removeApp(Application scope) { - if (removeAppWithoutCache(scope)) { - cacheScopes(); - return true; - } - return false; - } - public void setResourceHook(boolean resourceHook) { writeInt(resourceHookSwitch, resourceHook ? 1 : 0); this.resourceHook = resourceHook; diff --git a/core/src/main/java/io/github/lsposed/lspd/service/LSPApplicationService.java b/core/src/main/java/io/github/lsposed/lspd/service/LSPApplicationService.java index c743e530..95daf6f6 100644 --- a/core/src/main/java/io/github/lsposed/lspd/service/LSPApplicationService.java +++ b/core/src/main/java/io/github/lsposed/lspd/service/LSPApplicationService.java @@ -52,7 +52,7 @@ public class LSPApplicationService extends ILSPApplicationService.Stub { ensureRegistered(); int callingUid = Binder.getCallingUid(); if (callingUid == 1000 && processName.equals("android")) { - ConfigManager.getModulesPathForSystemServer(); + return ConfigManager.getInstance().getModulesPathForSystemServer(); } return ConfigManager.getInstance().getModulesPathForProcess(processName, callingUid); } diff --git a/core/src/main/java/io/github/lsposed/lspd/service/LSPosedService.java b/core/src/main/java/io/github/lsposed/lspd/service/LSPosedService.java index 37170bf8..a2e3375d 100644 --- a/core/src/main/java/io/github/lsposed/lspd/service/LSPosedService.java +++ b/core/src/main/java/io/github/lsposed/lspd/service/LSPosedService.java @@ -20,7 +20,7 @@ public class LSPosedService extends ILSPosedService.Stub { return null; } if (uid == 1000 && processName.equals("android")) { - if (ConfigManager.shouldSkipSystemServer()) + if (ConfigManager.getInstance().shouldSkipSystemServer()) return null; else return ServiceManager.getApplicationService(); diff --git a/core/src/main/java/io/github/lsposed/lspd/service/PackageService.java b/core/src/main/java/io/github/lsposed/lspd/service/PackageService.java index d6587c64..6a8a9a6a 100644 --- a/core/src/main/java/io/github/lsposed/lspd/service/PackageService.java +++ b/core/src/main/java/io/github/lsposed/lspd/service/PackageService.java @@ -8,11 +8,14 @@ import android.content.pm.ServiceInfo; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; +import android.util.Pair; import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; import java.util.Set; +import io.github.lsposed.lspd.Application; import io.github.lsposed.lspd.utils.ParceledListSlice; import static android.content.pm.ServiceInfo.FLAG_ISOLATED_PROCESS; @@ -41,14 +44,6 @@ public class PackageService { return pm.getPackagesForUid(uid); } - public static Set getProcessesForUid(int uid, int userId) throws RemoteException { - HashSet processNames = new HashSet<>(); - for (String packageName : getPackagesForUid(uid)) { - processNames.addAll(fetchProcesses(packageName, userId)); - } - return processNames; - } - public static ParceledListSlice getInstalledPackagesFromAllUsers(int flags) throws RemoteException { ArrayList res = new ArrayList<>(); IPackageManager pm = getPackageManager(); @@ -82,12 +77,14 @@ public class PackageService { return processNames; } - public static Set fetchProcesses(String packageName, int userId) throws RemoteException { + public static Pair, Integer> fetchProcessesWithUid(Application app) throws RemoteException { IPackageManager pm = getPackageManager(); - if (pm == null) return new HashSet<>(); - PackageInfo pkgInfo = pm.getPackageInfo(packageName, PackageManager.MATCH_DISABLED_COMPONENTS | + if (pm == null) return new Pair<>(Collections.emptySet(), -1); + PackageInfo pkgInfo = pm.getPackageInfo(app.packageName, PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_ACTIVITIES | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | - PackageManager.GET_SERVICES | PackageManager.GET_RECEIVERS | PackageManager.GET_PROVIDERS, userId); - return fetchProcesses(pkgInfo); + PackageManager.GET_SERVICES | PackageManager.GET_RECEIVERS | PackageManager.GET_PROVIDERS, app.userId); + if (pkgInfo == null || pkgInfo.applicationInfo == null) + return new Pair<>(Collections.emptySet(), -1); + return new Pair<>(fetchProcesses(pkgInfo), pkgInfo.applicationInfo.uid); } }