[skip ci]:

Fixing tools used by kernels under 5.10
-Add Slot selection is not displayed for non-ab partitions
This commit is contained in:
ShirkNeko
2025-05-05 22:09:01 +08:00
parent 349ca36d4e
commit caee2417d6
3 changed files with 46 additions and 59 deletions

View File

@@ -3,8 +3,10 @@
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<application <application

View File

@@ -133,15 +133,13 @@ class HorizonKernelWorker(
state.updateStep(context.getString(R.string.horizon_flashing)) state.updateStep(context.getString(R.string.horizon_flashing))
state.updateProgress(0.7f) state.updateProgress(0.7f)
// 获取原始槽位信息 val isAbDevice = isAbDevice()
if (slot != null) {
if (isAbDevice && slot != null) {
state.updateStep(context.getString(R.string.horizon_getting_original_slot)) state.updateStep(context.getString(R.string.horizon_getting_original_slot))
state.updateProgress(0.72f) state.updateProgress(0.72f)
originalSlot = runCommandGetOutput(true, "getprop ro.boot.slot_suffix") originalSlot = runCommandGetOutput(true, "getprop ro.boot.slot_suffix")
}
// 设置目标槽位
if (!slot.isNullOrEmpty()) {
state.updateStep(context.getString(R.string.horizon_setting_target_slot)) state.updateStep(context.getString(R.string.horizon_setting_target_slot))
state.updateProgress(0.74f) state.updateProgress(0.74f)
runCommand(true, "resetprop -n ro.boot.slot_suffix _$slot") runCommand(true, "resetprop -n ro.boot.slot_suffix _$slot")
@@ -149,8 +147,7 @@ class HorizonKernelWorker(
flash() flash()
// 恢复原始槽位 if (isAbDevice && !originalSlot.isNullOrEmpty()) {
if (!originalSlot.isNullOrEmpty()) {
state.updateStep(context.getString(R.string.horizon_restoring_original_slot)) state.updateStep(context.getString(R.string.horizon_restoring_original_slot))
state.updateProgress(0.8f) state.updateProgress(0.8f)
runCommand(true, "resetprop ro.boot.slot_suffix $originalSlot") runCommand(true, "resetprop ro.boot.slot_suffix $originalSlot")
@@ -165,8 +162,7 @@ class HorizonKernelWorker(
} catch (e: Exception) { } catch (e: Exception) {
state.setError(e.message ?: context.getString(R.string.horizon_unknown_error)) state.setError(e.message ?: context.getString(R.string.horizon_unknown_error))
// 恢复原始槽位 if (isAbDevice() && !originalSlot.isNullOrEmpty()) {
if (!originalSlot.isNullOrEmpty()) {
state.updateStep(context.getString(R.string.horizon_restoring_original_slot)) state.updateStep(context.getString(R.string.horizon_restoring_original_slot))
state.updateProgress(0.8f) state.updateProgress(0.8f)
runCommand(true, "resetprop ro.boot.slot_suffix $originalSlot") runCommand(true, "resetprop ro.boot.slot_suffix $originalSlot")
@@ -174,6 +170,17 @@ class HorizonKernelWorker(
} }
} }
// 检查设备是否为AB分区设备
private fun isAbDevice(): Boolean {
val abUpdate = runCommandGetOutput(true, "getprop ro.build.ab_update")?.trim() ?: ""
if (abUpdate.equals("false", ignoreCase = true) || abUpdate.isEmpty()) {
return false
}
val slotSuffix = runCommandGetOutput(true, "getprop ro.boot.slot_suffix")
return !slotSuffix.isNullOrEmpty()
}
private fun cleanup() { private fun cleanup() {
runCommand(false, "find ${context.filesDir.absolutePath} -type f ! -name '*.jpg' ! -name '*.png' -delete") runCommand(false, "find ${context.filesDir.absolutePath} -type f ! -name '*.jpg' ! -name '*.png' -delete")
} }
@@ -198,10 +205,18 @@ class HorizonKernelWorker(
private fun patch() { private fun patch() {
val kernelVersion = runCommandGetOutput(true, "cat /proc/version") val kernelVersion = runCommandGetOutput(true, "cat /proc/version")
val versionRegex = """\d+\.\d+\.\d+""".toRegex() val versionRegex = """\d+\.\d+\.\d+""".toRegex()
val version = versionRegex.find(kernelVersion)?.value ?: "" val version = kernelVersion?.let { versionRegex.find(it) }?.value ?: ""
val toolName = when { val toolName = if (version.isNotEmpty()) {
version.startsWith("5.10.") -> "5_10" val parts = version.split('.')
else -> "5_15+" if (parts.size >= 2) {
val major = parts[0].toIntOrNull() ?: 0
val minor = parts[1].toIntOrNull() ?: 0
if (major < 5 || (major == 5 && minor <= 10)) "5_10" else "5_15+"
} else {
"5_15+"
}
} else {
"5_15+"
} }
val toolPath = "${context.filesDir.absolutePath}/mkbootfs" val toolPath = "${context.filesDir.absolutePath}/mkbootfs"
AssetsUtil.exportFiles(context, "$toolName-mkbootfs", toolPath) AssetsUtil.exportFiles(context, "$toolName-mkbootfs", toolPath)
@@ -283,7 +298,7 @@ class HorizonKernelWorker(
} }
} }
private fun runCommandGetOutput(su: Boolean, cmd: String): String { private fun runCommandGetOutput(su: Boolean, cmd: String): String? {
val process = ProcessBuilder(if (su) "su" else "sh") val process = ProcessBuilder(if (su) "su" else "sh")
.redirectErrorStream(true) .redirectErrorStream(true)
.start() .start()

View File

@@ -115,6 +115,7 @@ fun InstallScreen(navigator: DestinationsNavigator) {
val summary = stringResource(R.string.horizon_kernel_summary) val summary = stringResource(R.string.horizon_kernel_summary)
val kernelVersion = getKernelVersion() val kernelVersion = getKernelVersion()
val isGKI = kernelVersion.isGKI() val isGKI = kernelVersion.isGKI()
val isAbDevice = isAbDevice()
val onFlashComplete = { val onFlashComplete = {
showRebootDialog = true showRebootDialog = true
@@ -169,7 +170,7 @@ fun InstallScreen(navigator: DestinationsNavigator) {
// 槽位选择 // 槽位选择
SlotSelectionDialog( SlotSelectionDialog(
show = showSlotSelectionDialog, show = showSlotSelectionDialog && isAbDevice,
onDismiss = { showSlotSelectionDialog = false }, onDismiss = { showSlotSelectionDialog = false },
onSlotSelected = { slot -> onSlotSelected = { slot ->
showSlotSelectionDialog = false showSlotSelectionDialog = false
@@ -240,10 +241,15 @@ fun InstallScreen(navigator: DestinationsNavigator) {
) { ) {
SelectInstallMethod( SelectInstallMethod(
isGKI = isGKI, isGKI = isGKI,
isAbDevice = isAbDevice,
onSelected = { method -> onSelected = { method ->
if (method is InstallMethod.HorizonKernel && method.uri != null && method.slot == null) { if (method is InstallMethod.HorizonKernel && method.uri != null) {
tempKernelUri = method.uri if (isAbDevice) {
showSlotSelectionDialog = true tempKernelUri = method.uri
showSlotSelectionDialog = true
} else {
installMethod = method
}
} else { } else {
installMethod = method installMethod = method
} }
@@ -395,6 +401,7 @@ sealed class InstallMethod {
@Composable @Composable
private fun SelectInstallMethod( private fun SelectInstallMethod(
isGKI: Boolean = false, isGKI: Boolean = false,
isAbDevice: Boolean = false,
onSelected: (InstallMethod) -> Unit = {} onSelected: (InstallMethod) -> Unit = {}
) { ) {
val rootAvailable = rootAvailable() val rootAvailable = rootAvailable()
@@ -488,7 +495,7 @@ private fun SelectInstallMethod(
modifier = Modifier.padding(horizontal = 16.dp) modifier = Modifier.padding(horizontal = 16.dp)
) { ) {
// LKM 安装/修补 // LKM 安装/修补
if (isGKI && rootAvailable) { if (isGKI) {
ElevatedCard( ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceVariant), colors = getCardColors(MaterialTheme.colorScheme.surfaceVariant),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation), elevation = CardDefaults.cardElevation(defaultElevation = cardElevation),
@@ -698,43 +705,6 @@ private fun SelectInstallMethod(
} }
} }
} }
// 没有root
if (!rootAvailable) {
ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.errorContainer),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 12.dp)
.clip(MaterialTheme.shapes.large)
.shadow(
elevation = cardElevation,
shape = MaterialTheme.shapes.large,
spotColor = MaterialTheme.colorScheme.error.copy(alpha = 0.1f)
)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(24.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = Icons.Filled.AutoFixHigh,
contentDescription = null,
tint = MaterialTheme.colorScheme.onErrorContainer,
modifier = Modifier
.padding(end = 16.dp)
)
Text(
text = stringResource(R.string.root_require_for_install),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onErrorContainer
)
}
}
}
} }
} }