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; }