diff --git a/app/src/main/java/org/lsposed/manager/ConfigManager.java b/app/src/main/java/org/lsposed/manager/ConfigManager.java
index f54b8b65..3851ca32 100644
--- a/app/src/main/java/org/lsposed/manager/ConfigManager.java
+++ b/app/src/main/java/org/lsposed/manager/ConfigManager.java
@@ -359,4 +359,13 @@ public class ConfigManager {
return false;
}
}
+
+ public static boolean dex2oatWrapperAlive() {
+ try {
+ return LSPManagerServiceHolder.getService().dex2oatWrapperAlive();
+ } catch (RemoteException e) {
+ Log.e(App.TAG, Log.getStackTraceString(e));
+ return false;
+ }
+ }
}
diff --git a/app/src/main/java/org/lsposed/manager/ui/fragment/HomeFragment.java b/app/src/main/java/org/lsposed/manager/ui/fragment/HomeFragment.java
index a1f2e0ac..76933a6f 100644
--- a/app/src/main/java/org/lsposed/manager/ui/fragment/HomeFragment.java
+++ b/app/src/main/java/org/lsposed/manager/ui/fragment/HomeFragment.java
@@ -107,7 +107,8 @@ public class HomeFragment extends BaseFragment {
} else {
binding.updateCard.setVisibility(View.GONE);
}
- if (!ConfigManager.isSepolicyLoaded() || !ConfigManager.systemServerRequested() || !ConfigManager.dex2oatFlagsLoaded()) {
+ boolean dex2oatAbnormal = !ConfigManager.dex2oatWrapperAlive() && !ConfigManager.dex2oatFlagsLoaded();
+ if (!ConfigManager.isSepolicyLoaded() || !ConfigManager.systemServerRequested() || dex2oatAbnormal) {
binding.statusTitle.setText(R.string.partial_activated);
binding.statusIcon.setImageResource(R.drawable.ic_round_warning_24);
binding.warningCard.setVisibility(View.VISIBLE);
@@ -119,14 +120,9 @@ public class HomeFragment extends BaseFragment {
binding.warningTitle.setText(R.string.system_inject_fail_summary);
binding.warningSummary.setText(HtmlCompat.fromHtml(getString(R.string.system_inject_fail), HtmlCompat.FROM_HTML_MODE_LEGACY));
}
- if (!ConfigManager.dex2oatFlagsLoaded()) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
- binding.warningTitle.setText(R.string.dex2oat_service_crashed_summary);
- binding.warningSummary.setText(HtmlCompat.fromHtml(getString(R.string.dex2oat_service_crashed), HtmlCompat.FROM_HTML_MODE_LEGACY));
- } else {
- binding.warningTitle.setText(R.string.system_prop_incorrect_summary);
- binding.warningSummary.setText(HtmlCompat.fromHtml(getString(R.string.system_prop_incorrect), HtmlCompat.FROM_HTML_MODE_LEGACY));
- }
+ if (dex2oatAbnormal) {
+ binding.warningTitle.setText(R.string.system_prop_incorrect_summary);
+ binding.warningSummary.setText(HtmlCompat.fromHtml(getString(R.string.system_prop_incorrect), HtmlCompat.FROM_HTML_MODE_LEGACY));
}
} else {
binding.warningCard.setVisibility(View.GONE);
@@ -161,6 +157,13 @@ public class HomeFragment extends BaseFragment {
binding.apiVersion.setText(String.valueOf(ConfigManager.getXposedApiVersion()));
binding.api.setText(ConfigManager.getApi());
binding.frameworkVersion.setText(String.format(LocaleDelegate.getDefaultLocale(), "%1$s (%2$d)", ConfigManager.getXposedVersionName(), ConfigManager.getXposedVersionCode()));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
+ binding.dex2oatWrapper.setText(R.string.unsupported_android_version);
+ } else if (ConfigManager.dex2oatWrapperAlive()) {
+ binding.dex2oatWrapper.setText(R.string.supported);
+ } else {
+ binding.dex2oatWrapper.setText(R.string.unsupported_crashed);
+ }
} else {
binding.apiVersion.setText(R.string.not_installed);
binding.api.setText(R.string.not_installed);
diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml
index 0ce486bd..31f12763 100644
--- a/app/src/main/res/layout/fragment_home.xml
+++ b/app/src/main/res/layout/fragment_home.xml
@@ -253,6 +253,19 @@
android:layout_height="wrap_content"
android:text="@string/not_installed" />
+
+
+
+
Please report this to Magisk developer.]]>
System Framework injection failed
Magisk or some low-quality Magisk modules.
Please try to disable Magisk modules other than Riru and LSPosed or submit full log to developers.]]>
- Dex optimizer service crashed
- Modules may invalidate occasionally or applications may become laggy.]]>
System prop incorrect
Modules may invalidate occasionally.]]>
Need to update
@@ -65,6 +63,10 @@
Device
System ABI
Injection Interface
+ Optimizer Wrapper
+ Supported
+ Unsupported (Android version unsatisfied)
+ Unsupported (Crashed)
Parasitic Manager Recommended
LSPosed now supports system parasitization to avoid detection. You can safely uninstall the manager after successfully creating a shortcut of the parasitic manager. In any case you can install the manager back from /data/adb/lspd/manager.apk.
Create shortcut
diff --git a/daemon/src/main/java/org/lsposed/lspd/service/Dex2OatService.java b/daemon/src/main/java/org/lsposed/lspd/service/Dex2OatService.java
index edf70935..e8e1b67a 100644
--- a/daemon/src/main/java/org/lsposed/lspd/service/Dex2OatService.java
+++ b/daemon/src/main/java/org/lsposed/lspd/service/Dex2OatService.java
@@ -22,6 +22,9 @@ package org.lsposed.lspd.service;
import android.net.LocalServerSocket;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
import android.os.SELinux;
import android.system.ErrnoException;
import android.system.Os;
@@ -29,8 +32,11 @@ import android.system.OsConstants;
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.RequiresApi;
+
import java.io.File;
import java.io.FileDescriptor;
+import java.io.IOException;
import java.io.InterruptedIOException;
import java.nio.file.Files;
import java.nio.file.Paths;
@@ -38,33 +44,36 @@ import java.util.Locale;
public class Dex2OatService {
- private static final String TAG = "Dex2OatService";
+ public static final String PROP_NAME = "dalvik.vm.dex2oat-flags";
+ public static final String PROP_VALUE = "--inline-max-code-units=0";
+ private static final String TAG = "LSPosedDex2Oat";
private static final String DEX2OAT_32 = "/apex/com.android.art/bin/dex2oat32";
private static final String DEX2OAT_64 = "/apex/com.android.art/bin/dex2oat64";
- private Thread thread = null;
+ private final Thread thread;
private LocalSocket serverSocket = null;
private LocalServerSocket server = null;
private FileDescriptor stockFd32 = null, stockFd64 = null;
- public void start() {
+ @RequiresApi(Build.VERSION_CODES.Q)
+ public Dex2OatService() {
thread = new Thread(() -> {
+ var devPath = Paths.get(getDevPath());
+ var sockPath = devPath.resolve("dex2oat.sock");
try {
Log.i(TAG, "dex2oat daemon start");
if (setSocketCreateContext("u:r:dex2oat:s0")) {
Log.d(TAG, "set socket context to u:r:dex2oat:s0");
} else {
- Log.e(TAG, "failed to set socket context");
+ throw new IOException("failed to set socket context");
}
- var devPath = getDevPath();
- var sockPath = devPath + "/dex2oat.sock";
- Files.createDirectories(Paths.get(devPath));
+ Files.createDirectories(devPath);
Log.d(TAG, "dev path: " + devPath);
serverSocket = new LocalSocket(LocalSocket.SOCKET_STREAM);
- serverSocket.bind(new LocalSocketAddress(sockPath, LocalSocketAddress.Namespace.FILESYSTEM));
+ serverSocket.bind(new LocalSocketAddress(sockPath.toString(), LocalSocketAddress.Namespace.FILESYSTEM));
server = new LocalServerSocket(serverSocket.getFileDescriptor());
- SELinux.setFileContext(sockPath, "u:object_r:magisk_file:s0");
+ SELinux.setFileContext(sockPath.toString(), "u:object_r:magisk_file:s0");
if (new File(DEX2OAT_32).exists()) stockFd32 = Os.open(DEX2OAT_32, OsConstants.O_RDONLY, 0);
if (new File(DEX2OAT_64).exists()) stockFd64 = Os.open(DEX2OAT_64, OsConstants.O_RDONLY, 0);
@@ -79,19 +88,33 @@ public class Dex2OatService {
Log.d(TAG, "sent fd" + lp);
}
}
- } catch (Exception e) {
+ } catch (Throwable e) {
Log.e(TAG, "dex2oat daemon crashed", e);
+ try {
+ server.close();
+ Files.delete(sockPath);
+ } catch (IOException ignored) {
+ }
+ try {
+ if (stockFd32 != null && stockFd32.valid()) Os.close(stockFd32);
+ if (stockFd64 != null && stockFd64.valid()) Os.close(stockFd64);
+ } catch (ErrnoException ignored) {
+ }
+ new Handler(Looper.getMainLooper()).post(Dex2OatService::fallback);
}
});
thread.start();
}
+ @RequiresApi(Build.VERSION_CODES.Q)
public boolean isAlive() {
return thread.isAlive();
}
private static native String getDevPath();
+ private static native void fallback();
+
private boolean setSocketCreateContext(String context) {
FileDescriptor fd = null;
try {
diff --git a/daemon/src/main/java/org/lsposed/lspd/service/LSPManagerService.java b/daemon/src/main/java/org/lsposed/lspd/service/LSPManagerService.java
index fa5a0fe6..f277ce69 100644
--- a/daemon/src/main/java/org/lsposed/lspd/service/LSPManagerService.java
+++ b/daemon/src/main/java/org/lsposed/lspd/service/LSPManagerService.java
@@ -84,8 +84,6 @@ import hidden.HiddenApiBridge;
import io.github.xposed.xposedservice.utils.ParceledListSlice;
public class LSPManagerService extends ILSPManagerService.Stub {
- private static final String PROP_NAME = "dalvik.vm.dex2oat-flags";
- private static final String PROP_VALUE = "--inline-max-code-units=0";
// this maybe useful when obtaining the manager binder
private static String RANDOM_UUID = null;
private static final String SHORTCUT_ID = "org.lsposed.manager.shortcut";
@@ -688,11 +686,7 @@ public class LSPManagerService extends ILSPManagerService.Stub {
@Override
public boolean dex2oatFlagsLoaded() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
- return ServiceManager.getDex2OatService().isAlive();
- } else {
- return SystemProperties.get(PROP_NAME).contains(PROP_VALUE);
- }
+ return SystemProperties.get(Dex2OatService.PROP_NAME).contains(Dex2OatService.PROP_VALUE);
}
@Override
@@ -783,4 +777,13 @@ public class LSPManagerService extends ILSPManagerService.Stub {
public void setDexObfuscate(boolean enabled) {
ConfigManager.getInstance().setDexObfuscate(enabled);
}
+
+ @Override
+ public boolean dex2oatWrapperAlive() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ return ServiceManager.getDex2OatService().isAlive();
+ } else {
+ return false;
+ }
+ }
}
diff --git a/daemon/src/main/java/org/lsposed/lspd/service/ServiceManager.java b/daemon/src/main/java/org/lsposed/lspd/service/ServiceManager.java
index 182bb24d..0afac332 100644
--- a/daemon/src/main/java/org/lsposed/lspd/service/ServiceManager.java
+++ b/daemon/src/main/java/org/lsposed/lspd/service/ServiceManager.java
@@ -29,6 +29,8 @@ import android.os.Looper;
import android.os.Process;
import android.util.Log;
+import androidx.annotation.RequiresApi;
+
import com.android.internal.os.BinderInternal;
import org.lsposed.daemon.BuildConfig;
@@ -54,6 +56,7 @@ public class ServiceManager {
private static final ExecutorService executorService = Executors.newCachedThreadPool();
+ @RequiresApi(Build.VERSION_CODES.Q)
public static Dex2OatService getDex2OatService() {
return dex2OatService;
}
@@ -104,11 +107,6 @@ public class ServiceManager {
logcatService = new LogcatService();
logcatService.start();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
- dex2OatService = new Dex2OatService();
- dex2OatService.start();
- }
-
Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
Looper.prepareMainLooper();
@@ -117,6 +115,9 @@ public class ServiceManager {
applicationService = new LSPApplicationService();
managerService = new LSPManagerService();
systemServerService = new LSPSystemServerService(systemServerMaxRetry);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ dex2OatService = new Dex2OatService();
+ }
systemServerService.putBinderForSystemServer();
diff --git a/daemon/src/main/jni/dex2oat.c b/daemon/src/main/jni/dex2oat.c
index 2d603415..d3d5e0d1 100644
--- a/daemon/src/main/jni/dex2oat.c
+++ b/daemon/src/main/jni/dex2oat.c
@@ -22,6 +22,11 @@
//
#include
+#include
+#include
+#include
+
+#include "logging.h"
char kTmpDir[] = "placeholder_/dev/0123456789abcdef";
@@ -29,3 +34,10 @@ JNIEXPORT jstring JNICALL
Java_org_lsposed_lspd_service_Dex2OatService_getDevPath(JNIEnv *env, jclass clazz) {
return (*env)->NewStringUTF(env, kTmpDir + 12);
}
+
+JNIEXPORT void JNICALL
+Java_org_lsposed_lspd_service_Dex2OatService_fallback(JNIEnv *env, jclass clazz) {
+ LOGI("do fallback");
+ system("nsenter -m -t 1 umount /apex/com.android.art/bin/dex2oat*");
+ __system_property_set("dalvik.vm.dex2oat-flags", "--inline-max-code-units=0");
+}
diff --git a/dex2oat/src/main/cpp/logging.h b/dex2oat/src/main/cpp/logging.h
index cb810dc7..30927519 100644
--- a/dex2oat/src/main/cpp/logging.h
+++ b/dex2oat/src/main/cpp/logging.h
@@ -3,7 +3,7 @@
#include
#ifndef LOG_TAG
-#define LOG_TAG "dex2oat-wrapper"
+#define LOG_TAG "LSPosedDex2Oat"
#endif
#ifdef LOG_DISABLED
diff --git a/services/manager-service/src/main/aidl/org/lsposed/lspd/ILSPManagerService.aidl b/services/manager-service/src/main/aidl/org/lsposed/lspd/ILSPManagerService.aidl
index 7fcbb9dc..9f375fe2 100644
--- a/services/manager-service/src/main/aidl/org/lsposed/lspd/ILSPManagerService.aidl
+++ b/services/manager-service/src/main/aidl/org/lsposed/lspd/ILSPManagerService.aidl
@@ -79,4 +79,6 @@ interface ILSPManagerService {
boolean getDexObfuscate() = 42;
void setDexObfuscate(boolean enable) = 43;
+
+ boolean dex2oatWrapperAlive() = 44;
}