From 8ad03e38e8fc7bfe20a20114d439792519dd3b31 Mon Sep 17 00:00:00 2001 From: Mygod Date: Sun, 15 May 2022 18:15:23 -0400 Subject: [PATCH] Add support for daemon launching without relocation Improves RAM usage and potentially addresses #368. Inspired by: https://github.com/topjohnwu/libsu/blob/fc42e8274e186c1982361f403ac0c76dad3ba1e7/service/src/main/java/com/topjohnwu/superuser/internal/RootServiceManager.java#L186 --- mobile/proguard-rules.pro | 2 +- .../be/mygod/librootkotlinx/RootServer.kt | 44 +++++++++++++------ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/mobile/proguard-rules.pro b/mobile/proguard-rules.pro index b49c0c57..47d32d54 100644 --- a/mobile/proguard-rules.pro +++ b/mobile/proguard-rules.pro @@ -22,7 +22,7 @@ #-renamesourcefileattribute SourceFile -if public class be.mygod.librootkotlinx.RootServer { - private void doInit(android.content.Context, java.lang.String); + private void doInit(android.content.Context, java.lang.String, boolean); } -keep class be.mygod.librootkotlinx.RootServer { public static void main(java.lang.String[]); diff --git a/mobile/src/main/java/be/mygod/librootkotlinx/RootServer.kt b/mobile/src/main/java/be/mygod/librootkotlinx/RootServer.kt index 0250482d..d1a33575 100644 --- a/mobile/src/main/java/be/mygod/librootkotlinx/RootServer.kt +++ b/mobile/src/main/java/be/mygod/librootkotlinx/RootServer.kt @@ -86,6 +86,7 @@ class RootServer { } } + class LaunchException(cause: Throwable) : RuntimeException("Failed to launch root daemon", cause) class UnexpectedExitException : RemoteException("Root process exited unexpectedly") private lateinit var process: Process @@ -130,7 +131,7 @@ class RootServer { Logger.me.w(line) } } - private fun doInit(context: Context, niceName: String) { + private fun doInit(context: Context, niceName: String, shouldRelocate: Boolean = false) { try { val (reader, writer) = try { process = ProcessBuilder("su").start() @@ -147,20 +148,25 @@ class RootServer { } try { val token2 = UUID.randomUUID().toString() - val persistence = File(context.codeCacheDir, ".librootkotlinx-uuid") - val uuid = context.packageName + '@' + try { - persistence.readText() - } catch (_: FileNotFoundException) { - UUID.randomUUID().toString().also { persistence.writeText(it) } - } - val (script, relocated) = AppProcess.relocateScript(uuid) - script.appendLine(AppProcess.launchString(context.packageCodePath, RootServer::class.java.name, - relocated, niceName) + " $token2") - writer.writeBytes(script.toString()) + writer.writeBytes(if (shouldRelocate) { + val persistence = File(context.codeCacheDir, ".librootkotlinx-uuid") + val uuid = context.packageName + '@' + try { + persistence.readText() + } catch (_: FileNotFoundException) { + UUID.randomUUID().toString().also { persistence.writeText(it) } + } + val (script, relocated) = AppProcess.relocateScript(uuid) + script.appendLine(AppProcess.launchString(context.packageCodePath, RootServer::class.java.name, + relocated, niceName) + " $token2") + script.toString() + } else { + AppProcess.launchString(context.packageCodePath, RootServer::class.java.name, AppProcess.myExe, + niceName) + " $token2\n" + }) writer.flush() reader.lookForToken(token2) // wait for ready signal } catch (e: Exception) { - throw RuntimeException("Failed to launch root daemon", e) + throw LaunchException(e) } output = writer require(!active) @@ -204,7 +210,19 @@ class RootServer { * @param niceName Name to call the rooted Java process. */ suspend fun init(context: Context, niceName: String = "${context.packageName}:root") { - withContext(Dispatchers.IO) { doInit(context, niceName) } + withContext(Dispatchers.IO) { + try { + doInit(context, niceName) + } catch (e: LaunchException) { + try { + doInit(context, niceName, true) + } catch (e2: LaunchException) { + e2.addSuppressed(e) + throw e2 + } + Logger.me.w("Root without relocation has failed", RuntimeException(e)) + } + } callbackListenerExit = GlobalScope.async(Dispatchers.IO) { val errorReader = async(Dispatchers.IO) { try {