manager: support offline patch

This commit is contained in:
weishu
2024-03-18 23:16:24 +08:00
parent 9759a779cd
commit 0c11d210a9
11 changed files with 62 additions and 164 deletions

View File

@@ -137,7 +137,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
@Parcelize @Parcelize
sealed class FlashIt : Parcelable { sealed class FlashIt : Parcelable {
data class FlashBoot(val bootUri: Uri? = null, val koUri: Uri, val ota: Boolean) : FlashIt() data class FlashBoot(val bootUri: Uri? = null, val ota: Boolean) : FlashIt()
data class FlashModule(val uri: Uri) : FlashIt() data class FlashModule(val uri: Uri) : FlashIt()
} }
@@ -150,7 +150,6 @@ fun flashIt(
when (flashIt) { when (flashIt) {
is FlashIt.FlashBoot -> installBoot( is FlashIt.FlashBoot -> installBoot(
flashIt.bootUri, flashIt.bootUri,
flashIt.koUri,
flashIt.ota, flashIt.ota,
onFinish, onFinish,
onStdout, onStdout,

View File

@@ -57,55 +57,17 @@ import me.weishu.kernelsu.ui.util.rootAvailable
@Destination @Destination
@Composable @Composable
fun InstallScreen(navigator: DestinationsNavigator) { fun InstallScreen(navigator: DestinationsNavigator) {
val scope = rememberCoroutineScope()
val loadingDialog = rememberLoadingDialog()
val context = LocalContext.current
var installMethod by remember { var installMethod by remember {
mutableStateOf<InstallMethod?>(null) mutableStateOf<InstallMethod?>(null)
} }
val onFileDownloaded = { uri: Uri -> val onClickInstall = {
installMethod?.let { method ->
installMethod?.let { val flashIt = FlashIt.FlashBoot(
scope.launch(Dispatchers.Main) { if (method is InstallMethod.SelectFile) method.uri else null,
when (it) { method is InstallMethod.DirectInstallToInactiveSlot
InstallMethod.DirectInstall -> {
navigator.navigate(
FlashScreenDestination(
FlashIt.FlashBoot(
null,
uri,
false
) )
) navigator.navigate(FlashScreenDestination(flashIt))
)
}
InstallMethod.DirectInstallToInactiveSlot -> {
navigator.navigate(
FlashScreenDestination(
FlashIt.FlashBoot(
null,
uri,
true
)
)
)
}
is InstallMethod.SelectFile -> {
navigator.navigate(
FlashScreenDestination(
FlashIt.FlashBoot(
it.uri,
uri,
false
)
)
)
}
}
}
} }
} }
@@ -124,45 +86,11 @@ fun InstallScreen(navigator: DestinationsNavigator) {
.fillMaxWidth() .fillMaxWidth()
.padding(16.dp) .padding(16.dp)
) { ) {
DownloadListener(context = context) { uri ->
onFileDownloaded(uri)
loadingDialog.hide()
}
val failedMessage = stringResource(id = R.string.failed_to_fetch_lkm_url)
val downloadingMessage = stringResource(id = R.string.downloading)
Button( Button(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
enabled = installMethod != null, enabled = installMethod != null,
onClick = { onClick = {
loadingDialog.showLoading() onClickInstall()
scope.launch(Dispatchers.IO) {
getLKMUrl().onFailure { throwable ->
loadingDialog.hide()
scope.launch(Dispatchers.Main) {
Toast.makeText(
context,
failedMessage.format(throwable.message),
Toast.LENGTH_SHORT
).show()
}
}.onSuccess { result ->
download(
context = context,
url = result.second,
fileName = result.first,
description = downloadingMessage.format(
result.first
),
onDownloaded = { uri ->
onFileDownloaded(uri)
loadingDialog.hide()
},
onDownloading = {}
)
}
}
}) { }) {
Text( Text(
stringResource(id = R.string.install_next), stringResource(id = R.string.install_next),

View File

@@ -143,7 +143,6 @@ fun installModule(
fun installBoot( fun installBoot(
bootUri: Uri?, bootUri: Uri?,
lkmUri: Uri,
ota: Boolean, ota: Boolean,
onFinish: (Boolean) -> Unit, onFinish: (Boolean) -> Unit,
onStdout: (String) -> Unit, onStdout: (String) -> Unit,
@@ -151,18 +150,6 @@ fun installBoot(
): Boolean { ): Boolean {
val resolver = ksuApp.contentResolver val resolver = ksuApp.contentResolver
with(resolver.openInputStream(lkmUri)) {
val lkmFile = File(ksuApp.cacheDir, "kernelsu.ko")
lkmFile.outputStream().use { output ->
this?.copyTo(output)
}
if (!lkmFile.exists()) {
onStdout("- kernelsu.ko not found")
onFinish(false)
return false
}
val bootFile = bootUri?.let { uri -> val bootFile = bootUri?.let { uri ->
with(resolver.openInputStream(uri)) { with(resolver.openInputStream(uri)) {
val bootFile = File(ksuApp.cacheDir, "boot.img") val bootFile = File(ksuApp.cacheDir, "boot.img")
@@ -175,7 +162,7 @@ fun installBoot(
} }
val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libmagiskboot.so") val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libmagiskboot.so")
var cmd = "boot-patch -m ${lkmFile.absolutePath} --magiskboot ${magiskboot.absolutePath}" var cmd = "boot-patch --magiskboot ${magiskboot.absolutePath}"
cmd += if (bootFile == null) { cmd += if (bootFile == null) {
// no boot.img, use -f to force install // no boot.img, use -f to force install
@@ -189,7 +176,8 @@ fun installBoot(
} }
// output dir // output dir
val downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) val downloadsDir =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
cmd += " -o $downloadsDir" cmd += " -o $downloadsDir"
val shell = createRootShell() val shell = createRootShell()
@@ -209,15 +197,13 @@ fun installBoot(
val result = val result =
shell.newJob().add("${getKsuDaemonPath()} $cmd").to(stdoutCallback, stderrCallback) shell.newJob().add("${getKsuDaemonPath()} $cmd").to(stdoutCallback, stderrCallback)
.exec() .exec()
Log.i("KernelSU", "install boot $lkmUri result: ${result.isSuccess}") Log.i("KernelSU", "install boot result: ${result.isSuccess}")
lkmFile.delete()
bootFile?.delete() bootFile?.delete()
// if boot uri is empty, it is direct install, when success, we should show reboot button // if boot uri is empty, it is direct install, when success, we should show reboot button
onFinish(bootUri == null && result.isSuccess) onFinish(bootUri == null && result.isSuccess)
return result.isSuccess return result.isSuccess
}
} }
fun reboot(reason: String = "") { fun reboot(reason: String = "") {
@@ -250,7 +236,8 @@ fun isInitBoot(): Boolean {
return file.exists() return file.exists()
} }
// https://source.android.com/docs/core/architecture/partitions/generic-boot // https://source.android.com/docs/core/architecture/partitions/generic-boot
return ShellUtils.fastCmd(shell, "getprop ro.product.first_api_level").trim().toInt() >= Build.VERSION_CODES.TIRAMISU return ShellUtils.fastCmd(shell, "getprop ro.product.first_api_level").trim()
.toInt() >= Build.VERSION_CODES.TIRAMISU
} }
fun overlayFsAvailable(): Boolean { fun overlayFsAvailable(): Boolean {

View File

@@ -109,8 +109,6 @@
<string name="enable_web_debugging">تمكين تصحيح أخطاء WebView</string> <string name="enable_web_debugging">تمكين تصحيح أخطاء WebView</string>
<string name="enable_web_debugging_summary">يمكن استخدامه لتصحيح أخطاء WebUI، يرجى تمكينه فقط عند الحاجة.</string> <string name="enable_web_debugging_summary">يمكن استخدامه لتصحيح أخطاء WebUI، يرجى تمكينه فقط عند الحاجة.</string>
<string name="install_next">التالي</string> <string name="install_next">التالي</string>
<string name="failed_to_fetch_lkm_url">فشل جلب رابط LKM: %1$s</string>
<string name="downloading">تحميل %1$s</string>
<string name="select_file">اختيار ملف</string> <string name="select_file">اختيار ملف</string>
<string name="direct_install">تثبيت مباشر (موصى به)</string> <string name="direct_install">تثبيت مباشر (موصى به)</string>
<string name="install_inactive_slot">التثبيت على فتحة غير نشطة (بعد OTA)</string> <string name="install_inactive_slot">التثبيت على فتحة غير نشطة (بعد OTA)</string>

View File

@@ -116,6 +116,4 @@
\nN\'utilisez cette option qu\'une fois la mise à jour OTA terminée. \nN\'utilisez cette option qu\'une fois la mise à jour OTA terminée.
\nContinuer?</string> \nContinuer?</string>
<string name="install_next">Suivant</string> <string name="install_next">Suivant</string>
<string name="downloading">Téléchargement de %1$s</string>
<string name="failed_to_fetch_lkm_url">Échec de la récupération de l\'URL du LKM: %1$s</string>
</resources> </resources>

View File

@@ -115,7 +115,5 @@
<string name="install_inactive_slot_warning">Seu dispositivo será FORÇADO a inicializar no slot inativo atual após uma reinicialização! <string name="install_inactive_slot_warning">Seu dispositivo será FORÇADO a inicializar no slot inativo atual após uma reinicialização!
\nSó use esta opção após a conclusão do OTA. \nSó use esta opção após a conclusão do OTA.
\nDeseja continuar?</string> \nDeseja continuar?</string>
<string name="downloading">Baixando %1$s</string>
<string name="install_next">Próximo</string> <string name="install_next">Próximo</string>
<string name="failed_to_fetch_lkm_url">Falha ao buscar a URL do LKM: %1$s</string>
</resources> </resources>

View File

@@ -112,8 +112,6 @@
<string name="open">Открыть</string> <string name="open">Открыть</string>
<string name="enable_web_debugging">Включить отладку WebView</string> <string name="enable_web_debugging">Включить отладку WebView</string>
<string name="enable_web_debugging_summary">Используется для отладки веб-интерфейса. Пожалуйста, включайте только при необходимости.</string> <string name="enable_web_debugging_summary">Используется для отладки веб-интерфейса. Пожалуйста, включайте только при необходимости.</string>
<string name="downloading">Загрузка %1$s</string>
<string name="failed_to_fetch_lkm_url">Не удалось получить LKM по адресу: %1$s</string>
<string name="direct_install">Прямая установка (Рекомендуется)</string> <string name="direct_install">Прямая установка (Рекомендуется)</string>
<string name="install_inactive_slot">Установка в неактивный слот (После OTA)</string> <string name="install_inactive_slot">Установка в неактивный слот (После OTA)</string>
<string name="install_next">Далее</string> <string name="install_next">Далее</string>

View File

@@ -117,6 +117,4 @@
\nBu seçeneği yalnızca OTA tamamlandıktan sonra kullanın. \nBu seçeneği yalnızca OTA tamamlandıktan sonra kullanın.
\nDevam edilsin mi?</string> \nDevam edilsin mi?</string>
<string name="install_next">Sonraki</string> <string name="install_next">Sonraki</string>
<string name="failed_to_fetch_lkm_url">LKM URL\'si getirilemedi: %1$s</string>
<string name="downloading">%1$s indiriliyor</string>
</resources> </resources>

View File

@@ -113,7 +113,5 @@
<string name="install_inactive_slot">安装到未使用的槽位OTA 后)</string> <string name="install_inactive_slot">安装到未使用的槽位OTA 后)</string>
<string name="install_inactive_slot_warning">将在重启后强制切换到另一个槽位!\n注意只能在 OTA 更新完成后的重启之前使用。\n确认</string> <string name="install_inactive_slot_warning">将在重启后强制切换到另一个槽位!\n注意只能在 OTA 更新完成后的重启之前使用。\n确认</string>
<string name="install_next">下一步</string> <string name="install_next">下一步</string>
<string name="failed_to_fetch_lkm_url">获取 LKM 链接失败:%1$s</string>
<string name="downloading">正在下载:%1$s</string>
<string name="select_file_tip">建议选择 %1$s 分区镜像</string> <string name="select_file_tip">建议选择 %1$s 分区镜像</string>
</resources> </resources>

View File

@@ -115,6 +115,4 @@
\n請問是否繼續</string> \n請問是否繼續</string>
<string name="direct_install">直接安裝(建議)</string> <string name="direct_install">直接安裝(建議)</string>
<string name="install_next">下一步</string> <string name="install_next">下一步</string>
<string name="failed_to_fetch_lkm_url">取得 LKM 下載鏈接失敗:%1$s</string>
<string name="downloading">正在下載:%1$s</string>
</resources> </resources>

View File

@@ -115,7 +115,5 @@
<string name="install_inactive_slot">Install to Inactive Slot (After OTA)</string> <string name="install_inactive_slot">Install to Inactive Slot (After OTA)</string>
<string name="install_inactive_slot_warning">Your device will be **FORCED** to boot to the current inactive slot after a reboot!\nOnly use this option after OTA is done.\nContinue?</string> <string name="install_inactive_slot_warning">Your device will be **FORCED** to boot to the current inactive slot after a reboot!\nOnly use this option after OTA is done.\nContinue?</string>
<string name="install_next">Next</string> <string name="install_next">Next</string>
<string name="failed_to_fetch_lkm_url">Failed to fetch LKM url: %1$s</string>
<string name="downloading">Downloading %1$s</string>
<string name="select_file_tip">%1$s partition image is recommended</string> <string name="select_file_tip">%1$s partition image is recommended</string>
</resources> </resources>