diff --git a/mobile/proguard-rules.pro b/mobile/proguard-rules.pro index 47d32d54..9f12fb55 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, boolean); + private void doInit(android.content.Context, boolean, java.lang.String); } -keep class be.mygod.librootkotlinx.RootServer { public static void main(java.lang.String[]); diff --git a/mobile/src/main/java/be/mygod/librootkotlinx/AppProcess.kt b/mobile/src/main/java/be/mygod/librootkotlinx/AppProcess.kt index 4d53e722..c8f2a792 100644 --- a/mobile/src/main/java/be/mygod/librootkotlinx/AppProcess.kt +++ b/mobile/src/main/java/be/mygod/librootkotlinx/AppProcess.kt @@ -71,6 +71,13 @@ object AppProcess { "/system/bin/app_process" } + /** + * Try to guess whether enabling relocation would work best. + * It seems some Android 5-7 devices give random permission denials without relocation. + * See also VPNHotspot#173. + */ + val shouldRelocateHeuristics get() = Build.VERSION.SDK_INT < 26 || myExeCanonical.startsWith("/data/") + /** * To workaround Samsung's stupid kernel patch that prevents exec, we need to relocate exe outside of /data. * See also: https://github.com/Chainfire/librootjava/issues/19 diff --git a/mobile/src/main/java/be/mygod/librootkotlinx/RootServer.kt b/mobile/src/main/java/be/mygod/librootkotlinx/RootServer.kt index ea2ddfca..4c4b99aa 100644 --- a/mobile/src/main/java/be/mygod/librootkotlinx/RootServer.kt +++ b/mobile/src/main/java/be/mygod/librootkotlinx/RootServer.kt @@ -131,7 +131,7 @@ class RootServer { Logger.me.w(line) } } - private fun doInit(context: Context, niceName: String, shouldRelocate: Boolean = false) { + private fun doInit(context: Context, shouldRelocate: Boolean, niceName: String) { try { val (reader, writer) = try { process = ProcessBuilder("su").start() @@ -207,22 +207,12 @@ class RootServer { * Initialize a RootServer synchronously, can throw a lot of exceptions. * * @param context Any [Context] from the app. + * @param shouldRelocate Whether app process should be copied first. See also [AppProcess.shouldRelocateHeuristics]. * @param niceName Name to call the rooted Java process. */ - suspend fun init(context: Context, niceName: String = "${context.packageName}:root") { - withContext(Dispatchers.IO) { - if (AppProcess.myExeCanonical.startsWith("/data/")) doInit(context, niceName, true) else try { // #173 - 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)) - } - } + suspend fun init(context: Context, shouldRelocate: Boolean = false, + niceName: String = "${context.packageName}:root") { + withContext(Dispatchers.IO) { doInit(context, shouldRelocate, niceName) } callbackListenerExit = GlobalScope.async(Dispatchers.IO) { val errorReader = async(Dispatchers.IO) { try { diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/root/RootManager.kt b/mobile/src/main/java/be/mygod/vpnhotspot/root/RootManager.kt index bdf8889f..59296baa 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/root/RootManager.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/root/RootManager.kt @@ -8,6 +8,7 @@ import be.mygod.librootkotlinx.* import be.mygod.vpnhotspot.App.Companion.app import be.mygod.vpnhotspot.util.Services import be.mygod.vpnhotspot.util.UnblockCentral +import com.google.firebase.crashlytics.FirebaseCrashlytics import kotlinx.parcelize.Parcelize import timber.log.Timber @@ -45,7 +46,10 @@ object RootManager : RootSession(), Logger { override suspend fun initServer(server: RootServer) { Logger.me = this - server.init(app.deviceStorage) + AppProcess.shouldRelocateHeuristics.let { + FirebaseCrashlytics.getInstance().setCustomKey("RootManager.relocateEnabled", it) + server.init(app.deviceStorage, it) + } server.execute(RootInit()) } }