[core] Fix caching logic
This commit is contained in:
parent
bde6b6dbc3
commit
56504a5f3b
|
|
@ -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<ProcessScope, Set<String>> 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<String> 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<ProcessScope> getAssociatedProcesses(Application app) throws RemoteException {
|
||||
PackageInfo pkgInfo = PackageService.getPackageInfo(app.packageName, 0, app.userId);
|
||||
Pair<Set<String>, Integer> result = PackageService.fetchProcessesWithUid(app);
|
||||
List<ProcessScope> 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<ProcessScope> 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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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<String> getProcessesForUid(int uid, int userId) throws RemoteException {
|
||||
HashSet<String> processNames = new HashSet<>();
|
||||
for (String packageName : getPackagesForUid(uid)) {
|
||||
processNames.addAll(fetchProcesses(packageName, userId));
|
||||
}
|
||||
return processNames;
|
||||
}
|
||||
|
||||
public static ParceledListSlice<PackageInfo> getInstalledPackagesFromAllUsers(int flags) throws RemoteException {
|
||||
ArrayList<PackageInfo> res = new ArrayList<>();
|
||||
IPackageManager pm = getPackageManager();
|
||||
|
|
@ -82,12 +77,14 @@ public class PackageService {
|
|||
return processNames;
|
||||
}
|
||||
|
||||
public static Set<String> fetchProcesses(String packageName, int userId) throws RemoteException {
|
||||
public static Pair<Set<String>, 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue