[core] Async cache (#221)

* [core] Async cache

* Wait for handler

* Resolve reviews

* Refine imports
This commit is contained in:
LoveSy 2021-02-27 22:48:27 +08:00 committed by GitHub
parent cf634decc1
commit d5ee8d3842
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 46 additions and 13 deletions

View File

@ -24,8 +24,11 @@ import android.content.pm.PackageInfo;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.SystemClock;
import android.system.ErrnoException;
import android.system.Os;
import android.util.Log;
@ -95,6 +98,14 @@ public class ConfigManager {
private static final File modulesLogPath = new File(logPath, "modules.log");
private static final File verboseLogPath = new File(logPath, "all.log");
private final Handler cacheHandler;
long lastModuleCacheTime = 0;
long requestModuleCacheTime = 0;
long lastScopeCacheTime = 0;
long requestScopeCacheTime = 0;
static class ProcessScope {
String processName;
int uid;
@ -137,9 +148,17 @@ public class ConfigManager {
private final ConcurrentHashMap<Integer, String> cachedModule = new ConcurrentHashMap<>();
private void updateCaches() {
cacheScopes();
cacheModules();
private void updateCaches(boolean sync) {
synchronized (this) {
requestScopeCacheTime = requestModuleCacheTime = SystemClock.elapsedRealtime();
}
if (sync) {
cacheModules();
cacheScopes();
} else {
cacheHandler.post(this::cacheModules);
cacheHandler.post(this::cacheScopes);
}
}
// for system server, cache is not yet ready, we need to query database for it
@ -231,8 +250,8 @@ public class ConfigManager {
if (PackageService.getPackageManager() != null) {
Log.d(TAG, "pm is ready, updating cache");
instance.packageStarted = true;
instance.cacheScopes();
instance.cacheModules();
// must ensure cache is valid for later usage
instance.updateCaches(true);
instance.updateManager();
}
}
@ -240,11 +259,15 @@ public class ConfigManager {
}
private ConfigManager() {
HandlerThread cacheThread = new HandlerThread("cache");
cacheThread.start();
cacheHandler = new Handler(cacheThread.getLooper());
createTables();
updateConfig();
isPermissive = readInt(selinuxPath, 1) == 0;
cacheScopes();
cacheModules();
// must ensure cache is valid for later usage
updateCaches(true);
}
private void createTables() {
@ -264,6 +287,8 @@ public class ConfigManager {
private synchronized void cacheModules() {
// skip caching when pm is not yet available
if (!packageStarted) return;
if (lastModuleCacheTime >= requestModuleCacheTime) return;
else lastModuleCacheTime = SystemClock.elapsedRealtime();
cachedModule.clear();
try (Cursor cursor = db.query("modules", new String[]{"module_pkg_name"},
"enabled = 1", null, null, null, null)) {
@ -299,6 +324,8 @@ public class ConfigManager {
private synchronized void cacheScopes() {
// skip caching when pm is not yet available
if (!packageStarted) return;
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"},
"enabled = 1", null, null, null, null)) {
@ -387,7 +414,8 @@ public class ConfigManager {
if (count < 0) {
count = db.updateWithOnConflict("modules", values, "module_pkg_name=?", new String[]{packageName}, SQLiteDatabase.CONFLICT_IGNORE);
}
updateCaches();
// Called by oneway binder
updateCaches(true);
return count >= 0;
}
@ -428,7 +456,8 @@ public class ConfigManager {
db.setTransactionSuccessful();
db.endTransaction();
}
updateCaches();
// Called by manager, should be async
updateCaches(false);
return true;
}
@ -449,7 +478,8 @@ public class ConfigManager {
public boolean removeModule(String packageName) {
boolean res = removeModuleWithoutCache(packageName);
updateCaches();
// called by oneway binder
updateCaches(true);
return res;
}
@ -479,7 +509,8 @@ public class ConfigManager {
db.setTransactionSuccessful();
db.endTransaction();
}
updateCaches();
// called by manager, should be async
updateCaches(false);
return true;
}
@ -496,13 +527,15 @@ public class ConfigManager {
db.setTransactionSuccessful();
db.endTransaction();
}
updateCaches();
// Called by manager, should be async
updateCaches(false);
return true;
}
public boolean removeApp(Application app) {
boolean res = removeAppWithoutCache(app);
updateCaches();
// Called by oneway binder
updateCaches(true);
return res;
}