Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/tiann/KernelSU into HEAD
Browse files Browse the repository at this point in the history
* 'main' of https://github.com/tiann/KernelSU:
  ksud: migrate to Rust 2024 edition
  ksud: upgrade nom to 8.0
  build(deps): bump the npm group in /website with 18 updates (tiann#2460)
  Translations update from Hosted Weblate (tiann#2425)
  build(deps): bump the crates group across 1 directory with 17 updates (tiann#2472)
  website: update translation (tiann#2471)
  Update Dependencies (tiann#2440)
  FAQ Slight spelling fix (tiann#2470)
  manager: allow multiple modules to be installed sequentially (tiann#2459)
  FAQ Edit regarding KernelSU support and wording change. (tiann#2468)
  Fix reference count leak in nuke_ext4_sysfs() (tiann#2467)
  fix: crash tiann#2463 (tiann#2465)
  feat: properly set OkHttp header (tiann#2463)
  Provide TMPDIR for boot image repacking (tiann#2458)
  manager: refine flashing module utilities
  • Loading branch information
YumeMichi committed Feb 25, 2025
2 parents b690bb7 + 4fdd3e0 commit 14502de
Show file tree
Hide file tree
Showing 39 changed files with 814 additions and 697 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/clippy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ jobs:
- name: Run clippy
run: |
cross clippy --manifest-path userspace/ksud/Cargo.toml --target aarch64-linux-android --release
cross clippy --manifest-path userspace/ksud/Cargo.toml --target x86_64-linux-android --release
cross clippy --manifest-path userspace/ksud/Cargo.toml --target x86_64-linux-android --release
4 changes: 2 additions & 2 deletions .github/workflows/deploy-website.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
node-version: latest
cache: yarn # or pnpm / yarn
cache-dependency-path: website/yarn.lock
- name: Setup Pages
Expand All @@ -64,4 +64,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@v4
2 changes: 2 additions & 0 deletions kernel/core_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,10 +308,12 @@ static void nuke_ext4_sysfs() {
const char* name = sb->s_type->name;
if (strcmp(name, "ext4") != 0) {
pr_info("nuke but module aren't mounted\n");
path_put(&path);
return;
}

ext4_unregister_sysfs(sb);
path_put(&path);
}

int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
package me.weishu.kernelsu

import android.app.Application
import android.system.Os
import coil.Coil
import coil.ImageLoader
import me.zhanghai.android.appiconloader.coil.AppIconFetcher
import me.zhanghai.android.appiconloader.coil.AppIconKeyer
import okhttp3.Cache
import okhttp3.OkHttpClient
import java.io.File
import java.util.Locale

lateinit var ksuApp: KernelSUApplication

class KernelSUApplication : Application() {

lateinit var okhttpClient: OkHttpClient

override fun onCreate() {
super.onCreate()
ksuApp = this
Expand All @@ -30,7 +36,20 @@ class KernelSUApplication : Application() {
if (!webroot.exists()) {
webroot.mkdir()
}

// Provide working env for rust's temp_dir()
Os.setenv("TMPDIR", cacheDir.absolutePath, true)

okhttpClient =
OkHttpClient.Builder().cache(Cache(File(cacheDir, "okhttp"), 10 * 1024 * 1024))
.addInterceptor { block ->
block.proceed(
block.request().newBuilder()
.header("User-Agent", "KernelSU/${BuildConfig.VERSION_CODE}")
.header("Accept-Language", Locale.getDefault().toLanguageTag()).build()
)
}.build()
}


}
}
67 changes: 43 additions & 24 deletions manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Flash.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
import me.weishu.kernelsu.R
import me.weishu.kernelsu.ui.component.KeyEventBlocker
import me.weishu.kernelsu.ui.util.FlashResult
import me.weishu.kernelsu.ui.util.LkmSelection
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
import me.weishu.kernelsu.ui.util.flashModule
Expand All @@ -65,23 +66,40 @@ import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

/**
* @author weishu
* @date 2023/1/1.
*/

enum class FlashingStatus {
FLASHING,
SUCCESS,
FAILED
}

/**
* @author weishu
* @date 2023/1/1.
*/
// Lets you flash modules sequentially when mutiple zipUris are selected
fun flashModulesSequentially(
uris: List<Uri>,
onStdout: (String) -> Unit,
onStderr: (String) -> Unit
): FlashResult {
for (uri in uris) {
flashModule(uri, onStdout, onStderr).apply {
if (code != 0) {
return FlashResult(code, err, showReboot)
}
}
}
return FlashResult(0, "", true)
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
@Destination<RootGraph>
fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {

var text by rememberSaveable { mutableStateOf("") }
var tempText : String
var tempText: String
val logContent = rememberSaveable { StringBuilder() }
var showFloatAction by rememberSaveable { mutableStateOf(false) }

Expand All @@ -98,16 +116,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
return@LaunchedEffect
}
withContext(Dispatchers.IO) {
flashIt(flashIt, onFinish = { showReboot, code ->
if (code != 0) {
text += "Error: exit code = $code.\nPlease save and check the log.\n"
}
if (showReboot) {
text += "\n\n\n"
showFloatAction = true
}
flashing = if (code == 0) FlashingStatus.SUCCESS else FlashingStatus.FAILED
}, onStdout = {
flashIt(flashIt, onStdout = {
tempText = "$it\n"
if (tempText.startsWith("")) { // clear command
text = tempText.substring(6)
Expand All @@ -117,7 +126,16 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
logContent.append(it).append("\n")
}, onStderr = {
logContent.append(it).append("\n")
})
}).apply {
if (code != 0) {
text += "Error code: $code.\n $err Please save and check the log.\n"
}
if (showReboot) {
text += "\n\n\n"
showFloatAction = true
}
flashing = if (code == 0) FlashingStatus.SUCCESS else FlashingStatus.FAILED
}
}
}

Expand Down Expand Up @@ -191,33 +209,34 @@ sealed class FlashIt : Parcelable {
data class FlashBoot(val boot: Uri? = null, val lkm: LkmSelection, val ota: Boolean) :
FlashIt()

data class FlashModule(val uri: Uri) : FlashIt()
data class FlashModules(val uris: List<Uri>) : FlashIt()

data object FlashRestore : FlashIt()

data object FlashUninstall : FlashIt()
}

fun flashIt(
flashIt: FlashIt, onFinish: (Boolean, Int) -> Unit,
flashIt: FlashIt,
onStdout: (String) -> Unit,
onStderr: (String) -> Unit
) {
when (flashIt) {
): FlashResult {
return when (flashIt) {
is FlashIt.FlashBoot -> installBoot(
flashIt.boot,
flashIt.lkm,
flashIt.ota,
onFinish,
onStdout,
onStderr
)

is FlashIt.FlashModule -> flashModule(flashIt.uri, onFinish, onStdout, onStderr)
is FlashIt.FlashModules -> {
flashModulesSequentially(flashIt.uris, onStdout, onStderr)
}

FlashIt.FlashRestore -> restoreBoot(onFinish, onStdout, onStderr)
FlashIt.FlashRestore -> restoreBoot(onStdout, onStderr)

FlashIt.FlashUninstall -> uninstallPermanently(onFinish, onStdout, onStderr)
FlashIt.FlashUninstall -> uninstallPermanently(onStdout, onStderr)
}
}

Expand Down
46 changes: 37 additions & 9 deletions manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Module.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.outlined.PlayArrow
import androidx.compose.material.icons.outlined.Download
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Checkbox
Expand All @@ -56,6 +57,7 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.rememberTopAppBarState
Expand Down Expand Up @@ -92,6 +94,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.weishu.kernelsu.Natives
import me.weishu.kernelsu.R
import me.weishu.kernelsu.ksuApp
import me.weishu.kernelsu.ui.component.ConfirmResult
import me.weishu.kernelsu.ui.component.SearchAppBar
import me.weishu.kernelsu.ui.component.rememberConfirmDialog
Expand All @@ -103,9 +106,9 @@ import me.weishu.kernelsu.ui.util.hasMagisk
import me.weishu.kernelsu.ui.util.reboot
import me.weishu.kernelsu.ui.util.toggleModule
import me.weishu.kernelsu.ui.util.uninstallModule
import me.weishu.kernelsu.ui.util.getFileName
import me.weishu.kernelsu.ui.viewmodel.ModuleViewModel
import me.weishu.kernelsu.ui.webui.WebUIActivity
import okhttp3.OkHttpClient

@OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph>
Expand Down Expand Up @@ -200,27 +203,51 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
floatingActionButton = {
if (!hideInstallButton) {
val moduleInstall = stringResource(id = R.string.module_install)
val confirmTitle = stringResource(R.string.module)
var zipUris by remember { mutableStateOf<List<Uri>>(emptyList()) }
val confirmDialog = rememberConfirmDialog(onConfirm = {
navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(zipUris)))
viewModel.markNeedRefresh()
})
val selectZipLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode != RESULT_OK) {
return@rememberLauncherForActivityResult
}
val data = it.data ?: return@rememberLauncherForActivityResult
val uri = data.data ?: return@rememberLauncherForActivityResult

navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(uri)))
val clipData = data.clipData

viewModel.markNeedRefresh()
val uris = mutableListOf<Uri>()
if (clipData != null) {
for (i in 0 until clipData.itemCount) {
clipData.getItemAt(i)?.uri?.let { uris.add(it) }
}
} else {
data.data?.let { uris.add(it) }
}

Log.i("ModuleScreen", "select zip result: ${it.data}")
if (uris.size == 1) {
navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(listOf(uris.first()))))
} else if (uris.size > 1) {
// multiple files selected
val moduleNames = uris.mapIndexed { index, uri -> "\n${index + 1}. ${uri.getFileName(context)}" }.joinToString("")
val confirmContent = context.getString(R.string.module_install_prompt_with_name, moduleNames)
zipUris = uris
confirmDialog.showConfirm(
title = confirmTitle,
content = confirmContent,
markdown = true
)
}
}

ExtendedFloatingActionButton(
onClick = {
// select the zip file to install
// Select the zip files to install
val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
type = "application/zip"
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
}
selectZipLauncher.launch(intent)
},
Expand All @@ -232,6 +259,7 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
snackbarHost = { SnackbarHost(hostState = snackBarHost) }
) { innerPadding ->

when {
hasMagisk -> {
Box(
Expand All @@ -254,7 +282,7 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
boxModifier = Modifier.padding(innerPadding),
onInstallModule = {
navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(it)))
navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(listOf(it))))
},
onClickModule = { id, name, hasWebUi ->
if (hasWebUi) {
Expand Down Expand Up @@ -314,7 +342,7 @@ private fun ModuleList(
val changelogResult = loadingDialog.withLoading {
withContext(Dispatchers.IO) {
runCatching {
OkHttpClient().newCall(
ksuApp.okhttpClient.newCall(
okhttp3.Request.Builder().url(changelogUrl).build()
).execute().body!!.string()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import android.os.Environment
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.core.content.ContextCompat
import me.weishu.kernelsu.ksuApp
import me.weishu.kernelsu.ui.util.module.LatestVersionInfo

/**
Expand Down Expand Up @@ -66,7 +67,7 @@ fun checkNewVersion(): LatestVersionInfo {
// default null value if failed
val defaultValue = LatestVersionInfo()
runCatching {
okhttp3.OkHttpClient().newCall(okhttp3.Request.Builder().url(url).build()).execute()
ksuApp.okhttpClient.newCall(okhttp3.Request.Builder().url(url).build()).execute()
.use { response ->
if (!response.isSuccessful) {
return defaultValue
Expand Down
Loading

0 comments on commit 14502de

Please sign in to comment.