Implement RemotePreferences edit
This commit is contained in:
parent
cfe15100c0
commit
87db036fdf
|
|
@ -2,7 +2,6 @@ package org.lsposed.lspd.impl;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
@ -53,8 +52,10 @@ public class LSPosedRemotePreferences implements SharedPreferences {
|
||||||
public LSPosedRemotePreferences(ILSPInjectedModuleService service, String group) {
|
public LSPosedRemotePreferences(ILSPInjectedModuleService service, String group) {
|
||||||
try {
|
try {
|
||||||
Bundle output = service.requestRemotePreferences(group, callback);
|
Bundle output = service.requestRemotePreferences(group, callback);
|
||||||
callback.onUpdate(output);
|
if (output.containsKey("map")) {
|
||||||
} catch (RemoteException e) {
|
mMap.putAll((Map<String, Object>) output.getSerializable("map"));
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
XposedBridge.log(e);
|
XposedBridge.log(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ import android.content.res.AssetManager;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.os.SELinux;
|
import android.os.SELinux;
|
||||||
import android.os.SharedMemory;
|
import android.os.SharedMemory;
|
||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ import android.os.SystemClock;
|
||||||
import android.permission.IPermissionManager;
|
import android.permission.IPermissionManager;
|
||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
import android.system.Os;
|
import android.system.Os;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
|
|
@ -447,21 +448,35 @@ public class ConfigManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateModulePrefs(String moduleName, int userId, String group, String key, Object value) {
|
public void updateModulePrefs(String moduleName, int userId, String group, String key, Object value) {
|
||||||
|
Map<String, Object> values = new HashMap<>();
|
||||||
|
values.put(key, value);
|
||||||
|
updateModulePrefs(moduleName, userId, group, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateModulePrefs(String moduleName, int userId, String group, Map<String, Object> values) {
|
||||||
var config = cachedConfig.computeIfAbsent(new Pair<>(moduleName, userId), module -> fetchModuleConfig(module.first, module.second));
|
var config = cachedConfig.computeIfAbsent(new Pair<>(moduleName, userId), module -> fetchModuleConfig(module.first, module.second));
|
||||||
var prefs = config.computeIfAbsent(group, g -> new ConcurrentHashMap<>());
|
var prefs = config.computeIfAbsent(group, g -> new ConcurrentHashMap<>());
|
||||||
if (value instanceof Serializable) {
|
executeInTransaction(() -> {
|
||||||
prefs.put(key, value);
|
var contents = new ContentValues();
|
||||||
var values = new ContentValues();
|
for (var entry : values.entrySet()) {
|
||||||
values.put("`group`", group);
|
var key = entry.getKey();
|
||||||
values.put("`key`", key);
|
var value = entry.getValue();
|
||||||
values.put("data", SerializationUtils.serialize((Serializable) value));
|
if (value instanceof Serializable) {
|
||||||
values.put("module_pkg_name", moduleName);
|
prefs.put(key, value);
|
||||||
values.put("user_id", String.valueOf(userId));
|
contents.put("`group`", group);
|
||||||
db.insertWithOnConflict("configs", null, values, SQLiteDatabase.CONFLICT_REPLACE);
|
contents.put("`key`", key);
|
||||||
} else {
|
contents.put("data", SerializationUtils.serialize((Serializable) value));
|
||||||
prefs.remove(key);
|
contents.put("module_pkg_name", moduleName);
|
||||||
db.delete("configs", "module_pkg_name=? and user_id=? and `group`=? and `key`=?", new String[]{moduleName, String.valueOf(userId), group, key});
|
contents.put("user_id", String.valueOf(userId));
|
||||||
}
|
} else {
|
||||||
|
prefs.remove(key);
|
||||||
|
db.delete("configs", "module_pkg_name=? and user_id=? and `group`=? and `key`=?", new String[]{moduleName, String.valueOf(userId), group, key});
|
||||||
|
}
|
||||||
|
if (contents.size() > 0) {
|
||||||
|
db.insertWithOnConflict("configs", null, contents, SQLiteDatabase.CONFLICT_REPLACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConcurrentHashMap<String, Object> getModulePrefs(String moduleName, int userId, String group) {
|
public ConcurrentHashMap<String, Object> getModulePrefs(String moduleName, int userId, String group) {
|
||||||
|
|
|
||||||
|
|
@ -19,19 +19,26 @@
|
||||||
|
|
||||||
package org.lsposed.lspd.service;
|
package org.lsposed.lspd.service;
|
||||||
|
|
||||||
|
import static org.lsposed.lspd.service.PackageService.PER_USER_RANGE;
|
||||||
|
|
||||||
import android.content.AttributionSource;
|
import android.content.AttributionSource;
|
||||||
|
import android.os.Binder;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.lsposed.daemon.BuildConfig;
|
import org.lsposed.daemon.BuildConfig;
|
||||||
import org.lsposed.lspd.models.Module;
|
import org.lsposed.lspd.models.Module;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
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;
|
||||||
|
|
||||||
|
|
@ -44,7 +51,8 @@ public class LSPModuleService extends IXposedService.Stub {
|
||||||
|
|
||||||
private final static Set<Integer> uidSet = ConcurrentHashMap.newKeySet();
|
private final static Set<Integer> uidSet = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
private final Module loadedModule;
|
private final @NonNull
|
||||||
|
Module loadedModule;
|
||||||
|
|
||||||
static void uidStarts(int uid) {
|
static void uidStarts(int uid) {
|
||||||
if (!uidSet.contains(uid)) {
|
if (!uidSet.contains(uid)) {
|
||||||
|
|
@ -90,32 +98,44 @@ public class LSPModuleService extends IXposedService.Stub {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LSPModuleService(Module module) {
|
LSPModuleService(@NonNull Module module) {
|
||||||
loadedModule = module;
|
loadedModule = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ensureModule() throws RemoteException {
|
||||||
|
var appId = Binder.getCallingUid() % PackageService.PER_USER_RANGE;
|
||||||
|
if (loadedModule.appId != appId) {
|
||||||
|
throw new RemoteException("Module " + loadedModule.packageName + " is not for uid " + Binder.getCallingUid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAPIVersion() {
|
public int getAPIVersion() throws RemoteException {
|
||||||
|
ensureModule();
|
||||||
return API;
|
return API;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFrameworkName() {
|
public String getFrameworkName() throws RemoteException {
|
||||||
|
ensureModule();
|
||||||
return "LSPosed";
|
return "LSPosed";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFrameworkVersion() {
|
public String getFrameworkVersion() throws RemoteException {
|
||||||
|
ensureModule();
|
||||||
return BuildConfig.VERSION_NAME;
|
return BuildConfig.VERSION_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getFrameworkVersionCode() {
|
public long getFrameworkVersionCode() throws RemoteException {
|
||||||
|
ensureModule();
|
||||||
return BuildConfig.VERSION_CODE;
|
return BuildConfig.VERSION_CODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getScope() {
|
public List<String> getScope() throws RemoteException {
|
||||||
|
ensureModule();
|
||||||
ArrayList<String> res = new ArrayList<>();
|
ArrayList<String> res = new ArrayList<>();
|
||||||
var scope = ConfigManager.getInstance().getModuleScope(loadedModule.packageName);
|
var scope = ConfigManager.getInstance().getModuleScope(loadedModule.packageName);
|
||||||
if (scope == null) return res;
|
if (scope == null) return res;
|
||||||
|
|
@ -126,19 +146,42 @@ public class LSPModuleService extends IXposedService.Stub {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void requestScope(String packageName) {
|
public void requestScope(String packageName) throws RemoteException {
|
||||||
|
ensureModule();
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bundle requestRemotePreferences(String group) {
|
public Bundle requestRemotePreferences(String group) throws RemoteException {
|
||||||
// TODO
|
ensureModule();
|
||||||
return null;
|
var bundle = new Bundle();
|
||||||
|
var userId = Binder.getCallingUid() % PER_USER_RANGE;
|
||||||
|
bundle.putSerializable("map", ConfigManager.getInstance().getModulePrefs(loadedModule.packageName, userId, group));
|
||||||
|
return bundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateRemotePreferences(String group, Bundle diff) {
|
public void updateRemotePreferences(String group, Bundle diff) throws RemoteException {
|
||||||
// TODO
|
ensureModule();
|
||||||
|
var userId = Binder.getCallingUid() / PackageService.PER_USER_RANGE;
|
||||||
|
Map<String, Object> values = new ArrayMap<>();
|
||||||
|
if (diff.containsKey("delete")) {
|
||||||
|
var deletes = diff.getStringArrayList("delete");
|
||||||
|
for (var key : deletes) {
|
||||||
|
values.put(key, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (diff.containsKey("put")) {
|
||||||
|
try {
|
||||||
|
var puts = (Map<?, ?>) diff.getSerializable("put");
|
||||||
|
for (var entry : puts.entrySet()) {
|
||||||
|
values.put((String) entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Log.e(TAG, "updateRemotePreferences: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConfigManager.getInstance().updateModulePrefs(loadedModule.packageName, userId, group, values);
|
||||||
((LSPInjectedModuleService) loadedModule.service).onUpdateRemotePreferences(group, diff);
|
((LSPInjectedModuleService) loadedModule.service).onUpdateRemotePreferences(group, diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue