@@ -41,6 +41,13 @@ fun getRootShell(globalMnt: Boolean = false): Shell {
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <T> withNewRootShell(
|
||||
globalMnt: Boolean = false,
|
||||
block: Shell.() -> T
|
||||
): T {
|
||||
return createRootShell(globalMnt).use(block)
|
||||
}
|
||||
|
||||
fun createRootShell(globalMnt: Boolean = false): Shell {
|
||||
Shell.enableVerboseLogging = BuildConfig.DEBUG
|
||||
val builder = Shell.Builder.create()
|
||||
@@ -66,8 +73,13 @@ fun createRootShell(globalMnt: Boolean = false): Shell {
|
||||
}
|
||||
|
||||
fun execKsud(args: String, newShell: Boolean = false): Boolean {
|
||||
val shell = if (newShell) createRootShell() else getRootShell()
|
||||
return ShellUtils.fastCmdResult(shell, "${getKsuDaemonPath()} $args")
|
||||
return if (newShell) {
|
||||
withNewRootShell {
|
||||
ShellUtils.fastCmdResult(this, "${getKsuDaemonPath()} $args")
|
||||
}
|
||||
} else {
|
||||
ShellUtils.fastCmdResult(getRootShell(), "${getKsuDaemonPath()} $args")
|
||||
}
|
||||
}
|
||||
|
||||
fun install() {
|
||||
@@ -128,8 +140,6 @@ fun installModule(
|
||||
}
|
||||
val cmd = "module install ${file.absolutePath}"
|
||||
|
||||
val shell = createRootShell()
|
||||
|
||||
val stdoutCallback: CallbackList<String?> = object : CallbackList<String?>() {
|
||||
override fun onAddElement(s: String?) {
|
||||
onStdout(s ?: "")
|
||||
@@ -142,9 +152,9 @@ fun installModule(
|
||||
}
|
||||
}
|
||||
|
||||
val result =
|
||||
shell.newJob().add("${getKsuDaemonPath()} $cmd").to(stdoutCallback, stderrCallback)
|
||||
.exec()
|
||||
val result = withNewRootShell {
|
||||
newJob().add("${getKsuDaemonPath()} $cmd").to(stdoutCallback, stderrCallback).exec()
|
||||
}
|
||||
Log.i("KernelSU", "install module $uri result: $result")
|
||||
|
||||
file.delete()
|
||||
@@ -157,7 +167,6 @@ fun installModule(
|
||||
fun restoreBoot(
|
||||
onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit
|
||||
): Boolean {
|
||||
val shell = createRootShell()
|
||||
val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libmagiskboot.so")
|
||||
|
||||
val stdoutCallback: CallbackList<String?> = object : CallbackList<String?>() {
|
||||
@@ -172,10 +181,11 @@ fun restoreBoot(
|
||||
}
|
||||
}
|
||||
|
||||
val result =
|
||||
shell.newJob().add("${getKsuDaemonPath()} boot-restore -f --magiskboot $magiskboot")
|
||||
val result = withNewRootShell {
|
||||
newJob().add("${getKsuDaemonPath()} boot-restore -f --magiskboot $magiskboot")
|
||||
.to(stdoutCallback, stderrCallback)
|
||||
.exec()
|
||||
}
|
||||
|
||||
onFinish(result.isSuccess, result.code)
|
||||
return result.isSuccess
|
||||
@@ -255,8 +265,6 @@ fun installBoot(
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
|
||||
cmd += " -o $downloadsDir"
|
||||
|
||||
val shell = createRootShell()
|
||||
|
||||
val stdoutCallback: CallbackList<String?> = object : CallbackList<String?>() {
|
||||
override fun onAddElement(s: String?) {
|
||||
onStdout(s ?: "")
|
||||
@@ -269,8 +277,9 @@ fun installBoot(
|
||||
}
|
||||
}
|
||||
|
||||
val result =
|
||||
shell.newJob().add("${getKsuDaemonPath()} $cmd").to(stdoutCallback, stderrCallback).exec()
|
||||
val result = withNewRootShell {
|
||||
newJob().add("${getKsuDaemonPath()} $cmd").to(stdoutCallback, stderrCallback).exec()
|
||||
}
|
||||
Log.i("KernelSU", "install boot result: ${result.isSuccess}")
|
||||
|
||||
bootFile?.delete()
|
||||
|
||||
@@ -12,7 +12,9 @@ fun getSELinuxStatus(): String {
|
||||
.build("sh")
|
||||
|
||||
val list = ArrayList<String>()
|
||||
val result = shell.newJob().add("getenforce").to(list, list).exec()
|
||||
val result = shell.use {
|
||||
it.newJob().add("getenforce").to(list, list).exec()
|
||||
}
|
||||
val output = result.out.joinToString("\n").trim()
|
||||
|
||||
if (result.isSuccess) {
|
||||
|
||||
@@ -84,14 +84,14 @@ public final class SuFilePathHandler implements WebViewAssetLoader.PathHandler {
|
||||
* which files can be loaded.
|
||||
* @throws IllegalArgumentException if the directory is not allowed.
|
||||
*/
|
||||
public SuFilePathHandler(@NonNull Context context, @NonNull File directory) {
|
||||
public SuFilePathHandler(@NonNull Context context, @NonNull File directory, Shell rootShell) {
|
||||
try {
|
||||
mDirectory = new File(getCanonicalDirPath(directory));
|
||||
if (!isAllowedInternalStorageDir(context)) {
|
||||
throw new IllegalArgumentException("The given directory \"" + directory
|
||||
+ "\" doesn't exist under an allowed app internal storage directory");
|
||||
}
|
||||
mShell = KsuCliKt.createRootShell(true);
|
||||
mShell = rootShell;
|
||||
} catch (IOException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Failed to resolve the canonical path for the given directory: "
|
||||
|
||||
@@ -10,12 +10,16 @@ import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.webkit.WebViewAssetLoader
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import me.weishu.kernelsu.ui.util.createRootShell
|
||||
import java.io.File
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
class WebUIActivity : ComponentActivity() {
|
||||
class WebUIActivity : ComponentActivity() {
|
||||
private lateinit var webviewInterface: WebViewInterface
|
||||
|
||||
private var rootShell: Shell? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val moduleId = intent.getStringExtra("id")!!
|
||||
@@ -26,11 +30,12 @@ class WebUIActivity : ComponentActivity() {
|
||||
WebView.setWebContentsDebuggingEnabled(prefs.getBoolean("enable_web_debugging", false))
|
||||
|
||||
val webRoot = File("/data/adb/modules/${moduleId}/webroot")
|
||||
val rootShell = createRootShell(true).also { this.rootShell = it }
|
||||
val webViewAssetLoader = WebViewAssetLoader.Builder()
|
||||
.setDomain("mui.kernelsu.org")
|
||||
.addPathHandler(
|
||||
"/",
|
||||
SuFilePathHandler(this, webRoot)
|
||||
SuFilePathHandler(this, webRoot, rootShell)
|
||||
)
|
||||
.build()
|
||||
|
||||
@@ -55,4 +60,9 @@ class WebUIActivity : ComponentActivity() {
|
||||
|
||||
setContentView(webView)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
runCatching { rootShell?.close() }
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import androidx.core.view.WindowInsetsControllerCompat
|
||||
import com.topjohnwu.superuser.CallbackList
|
||||
import com.topjohnwu.superuser.ShellUtils
|
||||
import me.weishu.kernelsu.ui.util.createRootShell
|
||||
import me.weishu.kernelsu.ui.util.withNewRootShell
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.util.concurrent.CompletableFuture
|
||||
@@ -23,8 +24,7 @@ class WebViewInterface(val context: Context, private val webView: WebView) {
|
||||
|
||||
@JavascriptInterface
|
||||
fun exec(cmd: String): String {
|
||||
val shell = createRootShell(true)
|
||||
return ShellUtils.fastCmd(shell, cmd)
|
||||
return withNewRootShell(true) { ShellUtils.fastCmd(this, cmd) }
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
@@ -59,8 +59,9 @@ class WebViewInterface(val context: Context, private val webView: WebView) {
|
||||
processOptions(finalCommand, options)
|
||||
finalCommand.append(cmd)
|
||||
|
||||
val shell = createRootShell(true)
|
||||
val result = shell.newJob().add(finalCommand.toString()).to(ArrayList(), ArrayList()).exec()
|
||||
val result = withNewRootShell(true) {
|
||||
newJob().add(finalCommand.toString()).to(ArrayList(), ArrayList()).exec()
|
||||
}
|
||||
val stdout = result.out.joinToString(separator = "\n")
|
||||
val stderr = result.err.joinToString(separator = "\n")
|
||||
|
||||
@@ -144,6 +145,8 @@ class WebViewInterface(val context: Context, private val webView: WebView) {
|
||||
webView.loadUrl(emitErrCode)
|
||||
}
|
||||
}
|
||||
}.whenComplete { _, _ ->
|
||||
runCatching { shell.close() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user