refactor: use PatchConfig and optimize module loading
[feat: Local mode runs without background manager](https://github.com/7723mod/NPatch/pulls/2)
This commit is contained in:
parent
5bbef84a43
commit
ed202bbb10
|
|
@ -6,40 +6,46 @@ import static org.lsposed.lspatch.share.Constants.ORIGINAL_APK_ASSET_PATH;
|
||||||
import android.app.ActivityThread;
|
import android.app.ActivityThread;
|
||||||
import android.app.LoadedApk;
|
import android.app.LoadedApk;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.res.CompatibilityInfo;
|
import android.content.res.CompatibilityInfo;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.system.Os;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
import org.lsposed.lspatch.loader.util.FileUtils;
|
import org.lsposed.lspatch.loader.util.FileUtils;
|
||||||
import org.lsposed.lspatch.loader.util.XLog;
|
import org.lsposed.lspatch.loader.util.XLog;
|
||||||
import org.lsposed.lspatch.service.LocalApplicationService;
|
import org.lsposed.lspatch.service.LocalApplicationService;
|
||||||
import org.lsposed.lspatch.service.RemoteApplicationService;
|
import org.lsposed.lspatch.service.RemoteApplicationService;
|
||||||
|
import org.lsposed.lspatch.share.PatchConfig;
|
||||||
import org.lsposed.lspd.core.Startup;
|
import org.lsposed.lspd.core.Startup;
|
||||||
|
import org.lsposed.lspd.models.Module;
|
||||||
import org.lsposed.lspd.service.ILSPApplicationService;
|
import org.lsposed.lspd.service.ILSPApplicationService;
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.attribute.PosixFilePermissions;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.zip.ZipFile;
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
|
import dalvik.system.DexFile;
|
||||||
|
import de.robv.android.xposed.XposedBridge;
|
||||||
import de.robv.android.xposed.XposedHelpers;
|
import de.robv.android.xposed.XposedHelpers;
|
||||||
import hidden.HiddenApiBridge;
|
import hidden.HiddenApiBridge;
|
||||||
|
|
||||||
|
|
@ -57,7 +63,7 @@ public class LSPApplication {
|
||||||
private static LoadedApk stubLoadedApk;
|
private static LoadedApk stubLoadedApk;
|
||||||
private static LoadedApk appLoadedApk;
|
private static LoadedApk appLoadedApk;
|
||||||
|
|
||||||
private static JSONObject config;
|
private static PatchConfig config;
|
||||||
|
|
||||||
public static boolean isIsolated() {
|
public static boolean isIsolated() {
|
||||||
return (android.os.Process.myUid() % PER_USER_RANGE) >= FIRST_APP_ZYGOTE_ISOLATED_UID;
|
return (android.os.Process.myUid() % PER_USER_RANGE) >= FIRST_APP_ZYGOTE_ISOLATED_UID;
|
||||||
|
|
@ -77,29 +83,47 @@ public class LSPApplication {
|
||||||
|
|
||||||
Log.d(TAG, "Initialize service client");
|
Log.d(TAG, "Initialize service client");
|
||||||
ILSPApplicationService service;
|
ILSPApplicationService service;
|
||||||
if (config.optBoolean("useManager")) {
|
if (config.useManager) {
|
||||||
service = new RemoteApplicationService(context);
|
try {
|
||||||
|
service = new RemoteApplicationService(context);
|
||||||
|
List<Module> m = service.getLegacyModulesList();
|
||||||
|
JSONArray moduleArr = new JSONArray();
|
||||||
|
for (Module module : m) {
|
||||||
|
JSONObject moduleObj = new JSONObject();
|
||||||
|
moduleObj.put("path",module.apkPath);
|
||||||
|
moduleObj.put("packageName",module.packageName);
|
||||||
|
moduleArr.put(moduleObj);
|
||||||
|
}
|
||||||
|
SharedPreferences shared = context.getSharedPreferences("npatch", Context.MODE_PRIVATE);
|
||||||
|
shared.edit().putString("modules",moduleArr.toString()).commit();
|
||||||
|
Log.e(TAG, "Success update module scope");
|
||||||
|
}catch (Exception e){
|
||||||
|
Log.e(TAG, "Failed to connect to manager, fallback to fixed local service");
|
||||||
|
service = new LocalApplicationService(context);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
service = new LocalApplicationService(context);
|
service = new LocalApplicationService(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
disableProfile(context);
|
|
||||||
Startup.initXposed(false, ActivityThread.currentProcessName(), context.getApplicationInfo().dataDir, service);
|
Startup.initXposed(false, ActivityThread.currentProcessName(), context.getApplicationInfo().dataDir, service);
|
||||||
Startup.bootstrapXposed();
|
Startup.bootstrapXposed();
|
||||||
// WARN: Since it uses `XResource`, the following class should not be initialized
|
// WARN: Since it uses `XResource`, the following class should not be initialized
|
||||||
// before forkPostCommon is invoke. Otherwise, you will get failure of XResources
|
// before forkPostCommon is invoke. Otherwise, you will get failure of XResources
|
||||||
|
|
||||||
Log.i(TAG, "Load modules");
|
Log.i(TAG, "Load modules");
|
||||||
LSPLoader.initModules(appLoadedApk);
|
LSPLoader.initModules(appLoadedApk);
|
||||||
Log.i(TAG, "Modules initialized");
|
Log.i(TAG, "Modules initialized");
|
||||||
|
|
||||||
switchAllClassLoader();
|
switchAllClassLoader();
|
||||||
SigBypass.doSigBypass(context, config.optInt("sigBypassLevel"));
|
SigBypass.doSigBypass(context, config.sigBypassLevel);
|
||||||
|
|
||||||
Log.i(TAG, "LSPatch bootstrap completed");
|
Log.i(TAG, "LSPatch bootstrap completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Context createLoadedApkWithContext() {
|
private static Context createLoadedApkWithContext() {
|
||||||
try {
|
try {
|
||||||
|
var timeStart = System.currentTimeMillis();
|
||||||
var mBoundApplication = XposedHelpers.getObjectField(activityThread, "mBoundApplication");
|
var mBoundApplication = XposedHelpers.getObjectField(activityThread, "mBoundApplication");
|
||||||
|
|
||||||
stubLoadedApk = (LoadedApk) XposedHelpers.getObjectField(mBoundApplication, "info");
|
stubLoadedApk = (LoadedApk) XposedHelpers.getObjectField(mBoundApplication, "info");
|
||||||
|
|
@ -109,13 +133,13 @@ public class LSPApplication {
|
||||||
|
|
||||||
try (var is = baseClassLoader.getResourceAsStream(CONFIG_ASSET_PATH)) {
|
try (var is = baseClassLoader.getResourceAsStream(CONFIG_ASSET_PATH)) {
|
||||||
BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||||
config = new JSONObject(streamReader.lines().collect(Collectors.joining()));
|
config = new Gson().fromJson(streamReader, PatchConfig.class);
|
||||||
} catch (Throwable e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Failed to parse config file", e);
|
Log.e(TAG, "Failed to load config file");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Log.i(TAG, "Use manager: " + config.optBoolean("useManager"));
|
Log.i(TAG, "Use manager: " + config.useManager);
|
||||||
Log.i(TAG, "Signature bypass level: " + config.optInt("sigBypassLevel"));
|
Log.i(TAG, "Signature bypass level: " + config.sigBypassLevel);
|
||||||
|
|
||||||
Path originPath = Paths.get(appInfo.dataDir, "cache/lspatch/origin/");
|
Path originPath = Paths.get(appInfo.dataDir, "cache/lspatch/origin/");
|
||||||
Path cacheApkPath;
|
Path cacheApkPath;
|
||||||
|
|
@ -125,9 +149,7 @@ public class LSPApplication {
|
||||||
|
|
||||||
appInfo.sourceDir = cacheApkPath.toString();
|
appInfo.sourceDir = cacheApkPath.toString();
|
||||||
appInfo.publicSourceDir = cacheApkPath.toString();
|
appInfo.publicSourceDir = cacheApkPath.toString();
|
||||||
if (config.has("appComponentFactory")) {
|
appInfo.appComponentFactory = config.appComponentFactory;
|
||||||
appInfo.appComponentFactory = config.optString("appComponentFactory");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Files.exists(cacheApkPath)) {
|
if (!Files.exists(cacheApkPath)) {
|
||||||
Log.i(TAG, "Extract original apk");
|
Log.i(TAG, "Extract original apk");
|
||||||
|
|
@ -137,10 +159,13 @@ public class LSPApplication {
|
||||||
Files.copy(is, cacheApkPath);
|
Files.copy(is, cacheApkPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheApkPath.toFile().setWritable(false);
|
cacheApkPath.toFile().setWritable(false);
|
||||||
|
|
||||||
var mPackages = (Map<?, ?>) XposedHelpers.getObjectField(activityThread, "mPackages");
|
var mPackages = (Map<?, ?>) XposedHelpers.getObjectField(activityThread, "mPackages");
|
||||||
mPackages.remove(appInfo.packageName);
|
mPackages.remove(appInfo.packageName);
|
||||||
appLoadedApk = activityThread.getPackageInfoNoCheck(appInfo, compatInfo);
|
appLoadedApk = activityThread.getPackageInfoNoCheck(appInfo, compatInfo);
|
||||||
|
|
||||||
XposedHelpers.setObjectField(mBoundApplication, "info", appLoadedApk);
|
XposedHelpers.setObjectField(mBoundApplication, "info", appLoadedApk);
|
||||||
|
|
||||||
var activityClientRecordClass = XposedHelpers.findClass("android.app.ActivityThread$ActivityClientRecord", ActivityThread.class.getClassLoader());
|
var activityClientRecordClass = XposedHelpers.findClass("android.app.ActivityThread$ActivityClientRecord", ActivityThread.class.getClassLoader());
|
||||||
|
|
@ -165,14 +190,16 @@ public class LSPApplication {
|
||||||
Log.i(TAG, "hooked app initialized: " + appLoadedApk);
|
Log.i(TAG, "hooked app initialized: " + appLoadedApk);
|
||||||
|
|
||||||
var context = (Context) XposedHelpers.callStaticMethod(Class.forName("android.app.ContextImpl"), "createAppContext", activityThread, stubLoadedApk);
|
var context = (Context) XposedHelpers.callStaticMethod(Class.forName("android.app.ContextImpl"), "createAppContext", activityThread, stubLoadedApk);
|
||||||
if (config.has("appComponentFactory")) {
|
if (config.appComponentFactory != null) {
|
||||||
try {
|
try {
|
||||||
context.getClassLoader().loadClass(appInfo.appComponentFactory);
|
context.getClassLoader().loadClass(config.appComponentFactory);
|
||||||
} catch (Throwable e) { // 捕捉更廣泛的類載入錯誤, 可能可以兼容部分加固如 360
|
} catch (Throwable e) {
|
||||||
Log.w(TAG, "Original AppComponentFactory not found: " + appInfo.appComponentFactory, e);
|
Log.w(TAG, "Original AppComponentFactory not found: " + config.appComponentFactory, e);
|
||||||
appInfo.appComponentFactory = null;
|
appInfo.appComponentFactory = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Log.i(TAG,"createLoadedApkWithContext cost: " + (System.currentTimeMillis() - timeStart) + "ms");
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e(TAG, "createLoadedApk", e);
|
Log.e(TAG, "createLoadedApk", e);
|
||||||
|
|
@ -180,55 +207,6 @@ public class LSPApplication {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void disableProfile(Context context) {
|
|
||||||
final ArrayList<String> codePaths = new ArrayList<>();
|
|
||||||
var appInfo = context.getApplicationInfo();
|
|
||||||
var pkgName = context.getPackageName();
|
|
||||||
if (appInfo == null) return;
|
|
||||||
if ((appInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
|
|
||||||
codePaths.add(appInfo.sourceDir);
|
|
||||||
}
|
|
||||||
if (appInfo.splitSourceDirs != null) {
|
|
||||||
Collections.addAll(codePaths, appInfo.splitSourceDirs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (codePaths.isEmpty()) {
|
|
||||||
// If there are no code paths there's no need to setup a profile file and register with
|
|
||||||
// the runtime,
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var profileDir = HiddenApiBridge.Environment_getDataProfilesDePackageDirectory(appInfo.uid / PER_USER_RANGE, pkgName);
|
|
||||||
|
|
||||||
var attrs = PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("r--------"));
|
|
||||||
|
|
||||||
for (int i = codePaths.size() - 1; i >= 0; i--) {
|
|
||||||
String splitName = i == 0 ? null : appInfo.splitNames[i - 1];
|
|
||||||
File curProfileFile = new File(profileDir, splitName == null ? "primary.prof" : splitName + ".split.prof").getAbsoluteFile();
|
|
||||||
Log.d(TAG, "Processing " + curProfileFile.getAbsolutePath());
|
|
||||||
try {
|
|
||||||
if (!curProfileFile.exists()) {
|
|
||||||
Files.createFile(curProfileFile.toPath(), attrs);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!curProfileFile.canWrite() && Files.size(curProfileFile.toPath()) == 0) {
|
|
||||||
Log.d(TAG, "Skip profile " + curProfileFile.getAbsolutePath());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (curProfileFile.exists() && !curProfileFile.delete()) {
|
|
||||||
try (var writer = new FileOutputStream(curProfileFile)) {
|
|
||||||
Log.d(TAG, "Failed to delete, try to clear content " + curProfileFile.getAbsolutePath());
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Log.e(TAG, "Failed to delete and clear profile file " + curProfileFile.getAbsolutePath(), e);
|
|
||||||
}
|
|
||||||
Os.chmod(curProfileFile.getAbsolutePath(), 00400);
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Log.e(TAG, "Failed to disable profile file " + curProfileFile.getAbsolutePath(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void switchAllClassLoader() {
|
private static void switchAllClassLoader() {
|
||||||
var fields = LoadedApk.class.getDeclaredFields();
|
var fields = LoadedApk.class.getDeclaredFields();
|
||||||
for (Field field : fields) {
|
for (Field field : fields) {
|
||||||
|
|
|
||||||
|
|
@ -1,84 +1,75 @@
|
||||||
package org.lsposed.lspatch.service;
|
package org.lsposed.lspatch.service;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.lsposed.lspatch.loader.util.FileUtils;
|
import org.json.JSONArray;
|
||||||
import org.lsposed.lspatch.share.Constants;
|
import org.json.JSONObject;
|
||||||
import org.lsposed.lspatch.util.ModuleLoader;
|
import org.lsposed.lspatch.util.ModuleLoader;
|
||||||
import org.lsposed.lspd.models.Module;
|
import org.lsposed.lspd.models.Module;
|
||||||
import org.lsposed.lspd.service.ILSPApplicationService;
|
import org.lsposed.lspd.service.ILSPApplicationService;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.zip.ZipFile;
|
|
||||||
|
|
||||||
public class LocalApplicationService extends ILSPApplicationService.Stub {
|
public class LocalApplicationService extends ILSPApplicationService.Stub {
|
||||||
|
|
||||||
private static final String TAG = "NPatch";
|
private static final String TAG = "NPatch";
|
||||||
|
private final List<Module> cachedModule;
|
||||||
private final List<Module> modules = new ArrayList<>();
|
public LocalApplicationService(Context context){
|
||||||
|
SharedPreferences shared = context.getSharedPreferences("npatch", Context.MODE_PRIVATE);
|
||||||
public LocalApplicationService(Context context) {
|
cachedModule = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
for (var name : context.getAssets().list("lspatch/modules")) {
|
JSONArray mArr = new JSONArray(shared.getString("modules", "{}"));
|
||||||
String packageName = name.substring(0, name.length() - 4);
|
Log.i(TAG,"use fixed local application service:"+shared.getString("modules", "{}"));
|
||||||
String modulePath = context.getCacheDir() + "/lspatch/" + packageName + "/";
|
for (int i = 0; i < mArr.length(); i++) {
|
||||||
String cacheApkPath;
|
JSONObject mObj = mArr.getJSONObject(i);
|
||||||
try (ZipFile sourceFile = new ZipFile(context.getPackageResourcePath())) {
|
Module m = new Module();
|
||||||
cacheApkPath = modulePath + sourceFile.getEntry(Constants.EMBEDDED_MODULES_ASSET_PATH + name).getCrc() + ".apk";
|
String path = mObj.getString("path");
|
||||||
}
|
String packageName = mObj.getString("packageName");
|
||||||
|
m.apkPath = path;
|
||||||
if (!Files.exists(Paths.get(cacheApkPath))) {
|
m.packageName = packageName;
|
||||||
Log.i(TAG, "Extract module apk: " + packageName);
|
if (!new File(m.apkPath).exists()){
|
||||||
FileUtils.deleteFolderIfExists(Paths.get(modulePath));
|
Log.i("NPatch","Module:" + m.packageName + " path not available, reset.");
|
||||||
Files.createDirectories(Paths.get(modulePath));
|
try {
|
||||||
try (var is = context.getAssets().open("lspatch/modules/" + name)) {
|
ApplicationInfo info = context.getPackageManager().getApplicationInfo(m.packageName, 0);
|
||||||
Files.copy(is, Paths.get(cacheApkPath));
|
m.apkPath = info.sourceDir;
|
||||||
|
Log.i("NPatch","Module:" + m.packageName + " path reset to " + m.apkPath);
|
||||||
|
}catch (Exception e){
|
||||||
|
Log.e("NPatch",Log.getStackTraceString(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m.file = ModuleLoader.loadModule(m.apkPath);
|
||||||
var module = new Module();
|
cachedModule.add(m);
|
||||||
module.apkPath = cacheApkPath;
|
|
||||||
module.packageName = packageName;
|
|
||||||
module.file = ModuleLoader.loadModule(cacheApkPath);
|
|
||||||
modules.add(module);
|
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
}catch (Exception e){
|
||||||
Log.e(TAG, "Error when initializing LocalApplicationServiceClient", e);
|
Log.e(TAG,Log.getStackTraceString(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isLogMuted() throws RemoteException {
|
public List<Module> getLegacyModulesList() throws RemoteException {
|
||||||
return false;
|
return cachedModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Module> getLegacyModulesList() {
|
public List<Module> getModulesList() throws RemoteException {
|
||||||
return modules;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Module> getModulesList() {
|
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPrefsPath(String packageName) {
|
public String getPrefsPath(String packageName) throws RemoteException {
|
||||||
return new File(Environment.getDataDirectory(), "data/" + packageName + "/shared_prefs/").getAbsolutePath();
|
return new File(Environment.getDataDirectory(), "data/" + packageName + "/shared_prefs/").getAbsolutePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ParcelFileDescriptor requestInjectedManagerBinder(List<IBinder> binder) {
|
public ParcelFileDescriptor requestInjectedManagerBinder(List<IBinder> binder) throws RemoteException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,4 +77,9 @@ public class LocalApplicationService extends ILSPApplicationService.Stub {
|
||||||
public IBinder asBinder() {
|
public IBinder asBinder() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLogMuted() throws RemoteException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ import android.os.ParcelFileDescriptor;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import org.lsposed.lspatch.share.Constants;
|
import org.lsposed.lspatch.share.Constants;
|
||||||
import org.lsposed.lspd.models.Module;
|
import org.lsposed.lspd.models.Module;
|
||||||
|
|
@ -48,7 +47,7 @@ public class RemoteApplicationService implements ILSPApplicationService {
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName name, IBinder binder) {
|
public void onServiceConnected(ComponentName name, IBinder binder) {
|
||||||
Log.i(TAG, "Manager binder received");
|
Log.i(TAG, "Manager binder received");
|
||||||
service = Stub.asInterface(binder);
|
service = ILSPApplicationService.Stub.asInterface(binder);
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,7 +75,6 @@ public class RemoteApplicationService implements ILSPApplicationService {
|
||||||
if (!success) throw new TimeoutException("Bind service timeout");
|
if (!success) throw new TimeoutException("Bind service timeout");
|
||||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException |
|
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException |
|
||||||
InterruptedException | TimeoutException e) {
|
InterruptedException | TimeoutException e) {
|
||||||
Toast.makeText(context, "Unable to connect to Manager", Toast.LENGTH_SHORT).show();
|
|
||||||
var r = new RemoteException("Failed to get manager binder");
|
var r = new RemoteException("Failed to get manager binder");
|
||||||
r.initCause(e);
|
r.initCause(e);
|
||||||
throw r;
|
throw r;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue