Add the function of obtaining and restoring the original slot, and display the current slot information in the slot selection dialog box
-It should be possible to fix the issue of selecting slot positions Signed-off-by: ShirkNeko 109797057+ShirkNeko@users.noreply.github.com
This commit is contained in:
@@ -90,6 +90,7 @@ class HorizonKernelWorker(
|
|||||||
private lateinit var binaryPath: String
|
private lateinit var binaryPath: String
|
||||||
|
|
||||||
private var onFlashComplete: (() -> Unit)? = null
|
private var onFlashComplete: (() -> Unit)? = null
|
||||||
|
private var originalSlot: String? = null
|
||||||
|
|
||||||
fun setOnFlashCompleteListener(listener: () -> Unit) {
|
fun setOnFlashCompleteListener(listener: () -> Unit) {
|
||||||
onFlashComplete = listener
|
onFlashComplete = listener
|
||||||
@@ -131,8 +132,30 @@ 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)
|
||||||
|
|
||||||
|
// 获取原始槽位信息
|
||||||
|
if (slot != null) {
|
||||||
|
state.updateStep(context.getString(R.string.horizon_getting_original_slot))
|
||||||
|
state.updateProgress(0.72f)
|
||||||
|
originalSlot = runCommandGetOutput(true, "getprop ro.boot.slot_suffix")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置目标槽位
|
||||||
|
if (!slot.isNullOrEmpty()) {
|
||||||
|
state.updateStep(context.getString(R.string.horizon_setting_target_slot))
|
||||||
|
state.updateProgress(0.74f)
|
||||||
|
runCommand(true, "resetprop -n ro.boot.slot_suffix _$slot")
|
||||||
|
}
|
||||||
|
|
||||||
flash()
|
flash()
|
||||||
|
|
||||||
|
// 恢复原始槽位
|
||||||
|
if (!originalSlot.isNullOrEmpty()) {
|
||||||
|
state.updateStep(context.getString(R.string.horizon_restoring_original_slot))
|
||||||
|
state.updateProgress(0.8f)
|
||||||
|
runCommand(true, "resetprop ro.boot.slot_suffix $originalSlot")
|
||||||
|
}
|
||||||
|
|
||||||
state.updateStep(context.getString(R.string.horizon_flash_complete_status))
|
state.updateStep(context.getString(R.string.horizon_flash_complete_status))
|
||||||
state.completeFlashing()
|
state.completeFlashing()
|
||||||
|
|
||||||
@@ -141,6 +164,13 @@ 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 (!originalSlot.isNullOrEmpty()) {
|
||||||
|
state.updateStep(context.getString(R.string.horizon_restoring_original_slot))
|
||||||
|
state.updateProgress(0.8f)
|
||||||
|
runCommand(true, "resetprop ro.boot.slot_suffix $originalSlot")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,12 +275,33 @@ class HorizonKernelWorker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun runCommandGetOutput(su: Boolean, cmd: String): String {
|
||||||
|
val process = ProcessBuilder(if (su) "su" else "sh")
|
||||||
|
.redirectErrorStream(true)
|
||||||
|
.start()
|
||||||
|
|
||||||
|
return try {
|
||||||
|
process.outputStream.bufferedWriter().use { writer ->
|
||||||
|
writer.write("$cmd\n")
|
||||||
|
writer.write("exit\n")
|
||||||
|
writer.flush()
|
||||||
|
}
|
||||||
|
process.inputStream.bufferedReader().use { reader ->
|
||||||
|
reader.readText().trim()
|
||||||
|
}
|
||||||
|
} catch (_: Exception) {
|
||||||
|
""
|
||||||
|
} finally {
|
||||||
|
process.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun rootAvailable(): Boolean {
|
private fun rootAvailable(): Boolean {
|
||||||
return try {
|
return try {
|
||||||
val process = Runtime.getRuntime().exec("su -c id")
|
val process = Runtime.getRuntime().exec("su -c id")
|
||||||
val exitValue = process.waitFor()
|
val exitValue = process.waitFor()
|
||||||
exitValue == 0
|
exitValue == 0
|
||||||
} catch (e: Exception) {
|
} catch (_: Exception) {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package com.sukisu.ultra.ui.component
|
package com.sukisu.ultra.ui.component
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -24,6 +26,20 @@ fun SlotSelectionDialog(
|
|||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
onSlotSelected: (String) -> Unit
|
onSlotSelected: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
var currentSlot by remember { mutableStateOf<String?>(null) }
|
||||||
|
var errorMessage by remember { mutableStateOf<String?>(null) }
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
try {
|
||||||
|
currentSlot = getCurrentSlot(context)
|
||||||
|
errorMessage = null
|
||||||
|
} catch (e: Exception) {
|
||||||
|
errorMessage = e.message
|
||||||
|
currentSlot = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (show) {
|
if (show) {
|
||||||
val cardColor = if (!ThemeConfig.useDynamicColor) {
|
val cardColor = if (!ThemeConfig.useDynamicColor) {
|
||||||
ThemeConfig.currentTheme.ButtonContrast
|
ThemeConfig.currentTheme.ButtonContrast
|
||||||
@@ -44,6 +60,27 @@ fun SlotSelectionDialog(
|
|||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
|
if (errorMessage != null) {
|
||||||
|
Text(
|
||||||
|
text = "Error: $errorMessage",
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
color = MaterialTheme.colorScheme.error,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Text(
|
||||||
|
text = stringResource(
|
||||||
|
id = R.string.current_slot,
|
||||||
|
currentSlot ?: "Unknown"
|
||||||
|
),
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = R.string.select_slot_description),
|
text = stringResource(id = R.string.select_slot_description),
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
@@ -99,3 +136,24 @@ fun SlotSelectionDialog(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取当前槽位信息
|
||||||
|
private fun getCurrentSlot(context: Context): String? {
|
||||||
|
return runCommandGetOutput(true, "getprop ro.boot.slot_suffix")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun runCommandGetOutput(su: Boolean, cmd: String): String? {
|
||||||
|
return try {
|
||||||
|
val process = ProcessBuilder(if (su) "su" else "sh").start()
|
||||||
|
process.outputStream.bufferedWriter().use { writer ->
|
||||||
|
writer.write("$cmd\n")
|
||||||
|
writer.write("exit\n")
|
||||||
|
writer.flush()
|
||||||
|
}
|
||||||
|
process.inputStream.bufferedReader().use { reader ->
|
||||||
|
reader.readText().trim()
|
||||||
|
}
|
||||||
|
} catch (_: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -287,4 +287,8 @@
|
|||||||
<!-- 错误信息 -->
|
<!-- 错误信息 -->
|
||||||
<string name="horizon_copy_failed">复制失败</string>
|
<string name="horizon_copy_failed">复制失败</string>
|
||||||
<string name="horizon_unknown_error">未知错误</string>
|
<string name="horizon_unknown_error">未知错误</string>
|
||||||
|
<string name="horizon_getting_original_slot">获取原有槽位</string>
|
||||||
|
<string name="horizon_setting_target_slot">设置指定槽位</string>
|
||||||
|
<string name="horizon_restoring_original_slot">恢复默认槽位</string>
|
||||||
|
<string name="current_slot">当前槽位:%1$s </string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -291,4 +291,8 @@
|
|||||||
<!-- Error Messages -->
|
<!-- Error Messages -->
|
||||||
<string name="horizon_copy_failed">Copy failed</string>
|
<string name="horizon_copy_failed">Copy failed</string>
|
||||||
<string name="horizon_unknown_error">Unknown error</string>
|
<string name="horizon_unknown_error">Unknown error</string>
|
||||||
|
<string name="horizon_getting_original_slot">Getting the original slot</string>
|
||||||
|
<string name="horizon_setting_target_slot">Setting the specified slot</string>
|
||||||
|
<string name="horizon_restoring_original_slot">Restore Default Slot</string>
|
||||||
|
<string name="current_slot">Current Slot:%1$s </string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user