[core] Cache & check module
This commit is contained in:
parent
f56cf01e9f
commit
a12336f69b
|
|
@ -15,7 +15,6 @@ public class LSPApplicationServiceClient implements ILSPApplicationService {
|
||||||
static IBinder serviceBinder = null;
|
static IBinder serviceBinder = null;
|
||||||
|
|
||||||
static String baseCachePath = null;
|
static String baseCachePath = null;
|
||||||
static String basePrefsPath = null;
|
|
||||||
static String processName = null;
|
static String processName = null;
|
||||||
|
|
||||||
public static LSPApplicationServiceClient serviceClient = null;
|
public static LSPApplicationServiceClient serviceClient = null;
|
||||||
|
|
@ -99,16 +98,14 @@ public class LSPApplicationServiceClient implements ILSPApplicationService {
|
||||||
return new String[0];
|
return new String[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getModulesList(){
|
public String[] getModulesList() {
|
||||||
return getModulesList(processName);
|
return getModulesList(processName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPrefsPath(String packageName) {
|
public String getPrefsPath(String packageName) {
|
||||||
try {
|
try {
|
||||||
if (basePrefsPath == null)
|
return service.getPrefsPath(packageName);
|
||||||
basePrefsPath = service.getPrefsPath("");
|
|
||||||
return basePrefsPath + File.separator + packageName;
|
|
||||||
} catch (RemoteException | NullPointerException ignored) {
|
} catch (RemoteException | NullPointerException ignored) {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.res.CompatibilityInfo;
|
import android.content.res.CompatibilityInfo;
|
||||||
import android.content.res.XResources;
|
import android.content.res.XResources;
|
||||||
|
import android.os.IBinder;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.util.Hookers;
|
import io.github.lsposed.lspd.util.Hookers;
|
||||||
import io.github.lsposed.lspd.util.MetaDataReader;
|
import io.github.lsposed.lspd.util.MetaDataReader;
|
||||||
|
|
@ -68,12 +69,6 @@ public class HandleBindAppHooker extends XC_MethodHook {
|
||||||
Utils.logD("processName=" + appProcessName +
|
Utils.logD("processName=" + appProcessName +
|
||||||
", packageName=" + reportedPackageName + ", appDataDir=" + appDataDir);
|
", packageName=" + reportedPackageName + ", appDataDir=" + appDataDir);
|
||||||
|
|
||||||
ComponentName instrumentationName = (ComponentName) XposedHelpers.getObjectField(bindData, "instrumentationName");
|
|
||||||
if (instrumentationName != null) {
|
|
||||||
Hookers.logD("Instrumentation detected, disabling framework for");
|
|
||||||
XposedBridge.disableHooks = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CompatibilityInfo compatInfo = (CompatibilityInfo) XposedHelpers.getObjectField(bindData, "compatInfo");
|
CompatibilityInfo compatInfo = (CompatibilityInfo) XposedHelpers.getObjectField(bindData, "compatInfo");
|
||||||
if (appInfo.sourceDir == null) {
|
if (appInfo.sourceDir == null) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -87,14 +82,14 @@ public class HandleBindAppHooker extends XC_MethodHook {
|
||||||
String processName = (String) XposedHelpers.getObjectField(bindData, "processName");
|
String processName = (String) XposedHelpers.getObjectField(bindData, "processName");
|
||||||
|
|
||||||
|
|
||||||
boolean isModule = false;
|
IBinder moduleBinder = serviceClient.requestModuleBinder();
|
||||||
|
boolean isModule = moduleBinder != null;
|
||||||
int xposedminversion = -1;
|
int xposedminversion = -1;
|
||||||
boolean xposedsharedprefs = false;
|
boolean xposedsharedprefs = false;
|
||||||
boolean xposedmigrateprefs = false;
|
boolean xposedmigrateprefs = false;
|
||||||
try {
|
try {
|
||||||
Map<String, Object> metaData = MetaDataReader.getMetaData(new File(appInfo.sourceDir));
|
|
||||||
isModule = metaData.containsKey("xposedmodule");
|
|
||||||
if (isModule) {
|
if (isModule) {
|
||||||
|
Map<String, Object> metaData = MetaDataReader.getMetaData(new File(appInfo.sourceDir));
|
||||||
Object minVersionRaw = metaData.get("xposedminversion");
|
Object minVersionRaw = metaData.get("xposedminversion");
|
||||||
if (minVersionRaw instanceof Integer) {
|
if (minVersionRaw instanceof Integer) {
|
||||||
xposedminversion = (Integer) minVersionRaw;
|
xposedminversion = (Integer) minVersionRaw;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
|
@ -83,6 +82,7 @@ public class ConfigManager {
|
||||||
public void onEvent(int event, @Nullable String path) {
|
public void onEvent(int event, @Nullable String path) {
|
||||||
updateConfig();
|
updateConfig();
|
||||||
cacheScopes();
|
cacheScopes();
|
||||||
|
cacheModules();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -126,6 +126,8 @@ public class ConfigManager {
|
||||||
|
|
||||||
private final ConcurrentHashMap<ProcessScope, Set<String>> cachedScope = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<ProcessScope, Set<String>> cachedScope = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private final ConcurrentHashMap<Integer, String> cachedModule = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
// for system server, cache is not yet ready, we need to query database for it
|
// for system server, cache is not yet ready, we need to query database for it
|
||||||
public boolean shouldSkipSystemServer() {
|
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)) {
|
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)) {
|
||||||
|
|
@ -214,6 +216,7 @@ public class ConfigManager {
|
||||||
Log.d(TAG, "pm is ready, updating cache");
|
Log.d(TAG, "pm is ready, updating cache");
|
||||||
instance.packageStarted = true;
|
instance.packageStarted = true;
|
||||||
instance.cacheScopes();
|
instance.cacheScopes();
|
||||||
|
instance.cacheModules();
|
||||||
instance.updateManager();
|
instance.updateManager();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -226,6 +229,7 @@ public class ConfigManager {
|
||||||
isPermissive = readInt(selinuxPath, 1) == 0;
|
isPermissive = readInt(selinuxPath, 1) == 0;
|
||||||
configObserver.startWatching();
|
configObserver.startWatching();
|
||||||
cacheScopes();
|
cacheScopes();
|
||||||
|
cacheModules();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createTables() {
|
private void createTables() {
|
||||||
|
|
@ -242,6 +246,41 @@ public class ConfigManager {
|
||||||
return processes;
|
return processes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private synchronized void cacheModules() {
|
||||||
|
// skip caching when pm is not yet available
|
||||||
|
if (!packageStarted) return;
|
||||||
|
cachedModule.clear();
|
||||||
|
try (Cursor cursor = db.query("modules", new String[]{"module_pkg_name"},
|
||||||
|
"enabled = 1", null, null, null, null)) {
|
||||||
|
if (cursor == null) {
|
||||||
|
Log.e(TAG, "db cache failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int pkgNameIdx = cursor.getColumnIndex("module_pkg_name");
|
||||||
|
HashSet<String> obsoleteModules = new HashSet<>();
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
String packageName = cursor.getString(pkgNameIdx);
|
||||||
|
try {
|
||||||
|
PackageInfo pkgInfo = PackageService.getPackageInfo(packageName, 0, 0);
|
||||||
|
if (pkgInfo != null && pkgInfo.applicationInfo != null) {
|
||||||
|
cachedModule.put(pkgInfo.applicationInfo.uid, pkgInfo.packageName);
|
||||||
|
} else {
|
||||||
|
obsoleteModules.add(packageName);
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String obsoleteModule : obsoleteModules) {
|
||||||
|
removeModule(obsoleteModule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.d(TAG, "cached modules");
|
||||||
|
for (int uid : cachedModule.keySet()) {
|
||||||
|
Log.d(TAG, cachedModule.get(uid) + "/" + uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized void cacheScopes() {
|
private synchronized void cacheScopes() {
|
||||||
// skip caching when pm is not yet available
|
// skip caching when pm is not yet available
|
||||||
if (!packageStarted) return;
|
if (!packageStarted) return;
|
||||||
|
|
@ -524,6 +563,34 @@ public class ConfigManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isModule(int uid) {
|
||||||
|
return cachedModule.containsKey(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recursivelyChown(File file, int uid, int gid) throws ErrnoException {
|
||||||
|
Os.chown(file.toString(), uid, gid);
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
for (File subFile : file.listFiles()) {
|
||||||
|
recursivelyChown(subFile, uid, gid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean ensureModulePrefsPermission(int uid) {
|
||||||
|
String packageName = cachedModule.get(uid);
|
||||||
|
if (packageName == null) return false;
|
||||||
|
File path = new File(getPrefsPath(packageName));
|
||||||
|
try {
|
||||||
|
if (path.exists() && !path.isDirectory()) path.delete();
|
||||||
|
if (!path.exists()) Files.createDirectories(path.toPath());
|
||||||
|
recursivelyChown(path, uid, 1000);
|
||||||
|
return true;
|
||||||
|
} catch (IOException | ErrnoException e) {
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// migrate setting
|
// migrate setting
|
||||||
@Keep
|
@Keep
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
@ -541,9 +608,9 @@ public class ConfigManager {
|
||||||
int userId = Integer.parseInt(dir.getName());
|
int userId = Integer.parseInt(dir.getName());
|
||||||
System.out.println("Processing user: " + userId);
|
System.out.println("Processing user: " + userId);
|
||||||
File conf = new File(dir, "conf");
|
File conf = new File(dir, "conf");
|
||||||
if (!conf.exists()) System.exit(0);
|
if (!conf.exists()) continue;
|
||||||
File enabledModules = new File(conf, "enabled_modules.list");
|
File enabledModules = new File(conf, "enabled_modules.list");
|
||||||
if (!enabledModules.exists()) System.exit(0);
|
if (!enabledModules.exists()) continue;
|
||||||
|
|
||||||
System.out.println("updating modules...");
|
System.out.println("updating modules...");
|
||||||
|
|
||||||
|
|
@ -577,6 +644,7 @@ public class ConfigManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.out.println("Applying scope");
|
||||||
for (HashMap.Entry<String, List<Application>> entry : modulesScope.entrySet()) {
|
for (HashMap.Entry<String, List<Application>> entry : modulesScope.entrySet()) {
|
||||||
getInstance().setModuleScope(entry.getKey(), entry.getValue());
|
getInstance().setModuleScope(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,11 +75,13 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
|
||||||
return ConfigManager.getInstance().getModulesLog(ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_APPEND);
|
return ConfigManager.getInstance().getModulesLog(ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_APPEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check if module
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder requestModuleBinder() throws RemoteException {
|
public IBinder requestModuleBinder() throws RemoteException {
|
||||||
ensureRegistered();
|
ensureRegistered();
|
||||||
return ServiceManager.getModuleService();
|
if (ConfigManager.getInstance().isModule(Binder.getCallingUid())) {
|
||||||
|
ConfigManager.getInstance().ensureModulePrefsPermission(Binder.getCallingUid());
|
||||||
|
return ServiceManager.getModuleService();
|
||||||
|
} else return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue