From 0a838f7335e6f4e41f01cd70d9d509aefc946ebf Mon Sep 17 00:00:00 2001 From: nift4 Date: Mon, 26 Aug 2024 13:33:01 +0200 Subject: [PATCH] lazy initial sdless impl (missing parttool, create & update flows) --- .../org/andbootmgr/app/BackupRestoreFlow.kt | 35 ++++++---- .../java/org/andbootmgr/app/CreatePartFlow.kt | 8 +-- .../java/org/andbootmgr/app/DeviceInfo.kt | 13 ++++ .../java/org/andbootmgr/app/DeviceLogic.kt | 26 ++++++- .../java/org/andbootmgr/app/DroidBootFlow.kt | 70 +++++++++++++++---- .../org/andbootmgr/app/FixDroidBootFlow.kt | 8 ++- .../java/org/andbootmgr/app/MainActivity.kt | 16 +++-- app/src/main/java/org/andbootmgr/app/Start.kt | 13 +++- .../org/andbootmgr/app/UpdateDroidBootFlow.kt | 2 +- .../java/org/andbootmgr/app/UpdateFlow.kt | 2 +- .../java/org/andbootmgr/app/util/SDUtils.kt | 4 +- app/src/main/res/values/strings.xml | 7 ++ 12 files changed, 158 insertions(+), 46 deletions(-) diff --git a/app/src/main/java/org/andbootmgr/app/BackupRestoreFlow.kt b/app/src/main/java/org/andbootmgr/app/BackupRestoreFlow.kt index be5a9922..622aa016 100644 --- a/app/src/main/java/org/andbootmgr/app/BackupRestoreFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/BackupRestoreFlow.kt @@ -22,9 +22,9 @@ import org.andbootmgr.app.util.SDUtils import java.io.File import java.io.IOException -class BackupRestoreFlow(private val partitionId: Int): WizardFlow() { +class BackupRestoreFlow(private val partitionId: Int, private val partFile: File?): WizardFlow() { override fun get(vm: WizardState): List { - val c = CreateBackupDataHolder(vm, partitionId) + val c = CreateBackupDataHolder(vm, partitionId, partFile) return listOf(WizardPage("start", NavButton(vm.activity.getString(R.string.cancel)) { it.finish() }, NavButton("") {}) @@ -44,7 +44,7 @@ class BackupRestoreFlow(private val partitionId: Int): WizardFlow() { } } -private class CreateBackupDataHolder(val vm: WizardState, val pi: Int) { +private class CreateBackupDataHolder(val vm: WizardState, val pi: Int?, val partFile: File?) { var action: Int = 0 var path: Uri? = null var meta: SDUtils.SDPartitionMeta? = null @@ -52,14 +52,18 @@ private class CreateBackupDataHolder(val vm: WizardState, val pi: Int) { @Composable private fun ChooseAction(c: CreateBackupDataHolder) { - LaunchedEffect(Unit) { - c.meta = SDUtils.generateMeta(c.vm.deviceInfo) + if (c.vm.deviceInfo.metaonsd) { + LaunchedEffect(Unit) { + c.meta = SDUtils.generateMeta(c.vm.deviceInfo) + } } Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, modifier = Modifier.fillMaxSize() ) { - Text(stringResource(id = R.string.backup_msg, c.meta!!.dumpKernelPartition(c.pi).name), textAlign = TextAlign.Center) + val name = if (c.vm.deviceInfo.metaonsd) + c.meta!!.dumpKernelPartition(c.pi!!).name else c.partFile!!.name + Text(stringResource(id = R.string.backup_msg, name), textAlign = TextAlign.Center) Button(onClick = { c.action=1; c.vm.navigate("select") }) { Text(stringResource(R.string.backup)) } @@ -93,6 +97,8 @@ private fun SelectDroidBoot(c: CreateBackupDataHolder) { } ) Button(onClick = { + val name = if (c.vm.deviceInfo.metaonsd) + c.meta!!.dumpKernelPartition(c.pi!!).name else c.partFile!!.nameWithoutExtension if (c.action != 1) { c.vm.activity.chooseFile("*/*") { c.vm.chosen["file"] = WizardState.DownloadedFile(it, null) @@ -101,7 +107,7 @@ private fun SelectDroidBoot(c: CreateBackupDataHolder) { c.vm.onNext = { i -> i.navigate("go") } } } else { - c.vm.activity.createFile("${c.meta!!.dumpKernelPartition(c.pi).name}.img") { + c.vm.activity.createFile("${name}.img") { c.path = it nextButtonAvailable = true c.vm.nextText = c.vm.activity.getString(R.string.next) @@ -120,25 +126,28 @@ private fun Flash(c: CreateBackupDataHolder) { WizardTerminalWork(c.vm, logFile = "flash_${System.currentTimeMillis()}.txt") { terminal -> c.vm.logic.extractToolkit(terminal) terminal.add(c.vm.activity.getString(R.string.term_starting)) - val p = c.meta!!.dumpKernelPartition(c.pi) - if (!c.vm.logic.unmount(p).to(terminal).exec().isSuccess) - throw IOException(c.vm.activity.getString(R.string.term_cant_umount)) + val path = if (c.vm.deviceInfo.metaonsd) { + val p = c.meta!!.dumpKernelPartition(c.pi!!) + if (!c.vm.logic.unmount(p).to(terminal).exec().isSuccess) + throw IOException(c.vm.activity.getString(R.string.term_cant_umount)) + p.path + } else c.partFile!!.absolutePath if (c.action == 1) { c.vm.copy( - SuFileInputStream.open(File(p.path)), + SuFileInputStream.open(path), c.vm.activity.contentResolver.openOutputStream(c.path!!)!! ) } else if (c.action == 2) { c.vm.copyPriv( c.vm.chosen["file"]!!.openInputStream(c.vm), - File(p.path) + File(path) ) } else if (c.action == 3) { val result2 = Shell.cmd( File( c.vm.logic.toolkitDir, "simg2img" - ).absolutePath + " ${c.vm.chosen["file"]!!.toFile(c.vm).absolutePath} ${p.path}" + ).absolutePath + " ${c.vm.chosen["file"]!!.toFile(c.vm).absolutePath} $path" ).to(terminal).exec() if (!result2.isSuccess) { terminal.add(c.vm.activity.getString(R.string.term_failure)) diff --git a/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt b/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt index 8f93b87c..d8a4a2f1 100644 --- a/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt @@ -137,7 +137,7 @@ private fun Start(c: CreatePartDataHolder) { LaunchedEffect(Unit) { if (c.meta == null) { withContext(Dispatchers.IO) { - val meta = SDUtils.generateMeta(c.vm.deviceInfo)!! + val meta = SDUtils.generateMeta(c.vm.deviceInfo)!! // TODO !metaonsd c.p = meta.s.find { c.desiredStartSector == it.startSector } as SDUtils.Partition.FreeSpace c.meta = meta @@ -663,12 +663,12 @@ private fun Flash(c: CreatePartDataHolder) { tmpFile.setExecutable(true) terminal.add(vm.activity.getString(R.string.term_creating_pt)) - vm.logic.unmountBootset() + vm.logic.unmountBootset(vm.deviceInfo) val startSectorAbsolute = c.p.startSector + c.startSectorRelative val endSectorAbsolute = c.p.startSector + c.endSectorRelative if (endSectorAbsolute > c.p.endSector) throw IllegalArgumentException("$endSectorAbsolute can't be bigger than ${c.p.endSector}") - c.parts.forEachIndexed { index, part -> + c.parts.forEachIndexed { index, part -> // TODO !metaonsd terminal.add(vm.activity.getString(R.string.term_create_part)) val start = c.p.startSector.coerceAtLeast(startSectorAbsolute) val end = c.p.endSector.coerceAtMost(endSectorAbsolute) @@ -765,7 +765,7 @@ private fun Flash(c: CreatePartDataHolder) { terminal.add(vm.activity.getString(R.string.term_success)) } else { // Portable partition terminal.add(vm.activity.getString(R.string.term_create_part)) - vm.logic.unmountBootset() + vm.logic.unmountBootset(vm.deviceInfo) val r = vm.logic.create(c.p, c.startSectorRelative, c.endSectorRelative, diff --git a/app/src/main/java/org/andbootmgr/app/DeviceInfo.kt b/app/src/main/java/org/andbootmgr/app/DeviceInfo.kt index 89444210..f86b0f14 100644 --- a/app/src/main/java/org/andbootmgr/app/DeviceInfo.kt +++ b/app/src/main/java/org/andbootmgr/app/DeviceInfo.kt @@ -58,6 +58,19 @@ abstract class MetaOnSdDeviceInfo : DeviceInfo { override fun isCorrupt(logic: DeviceLogic): Boolean { return !SuFile.open(logic.abmDb, "db.conf").exists() } + override fun getAbmSettings(logic: DeviceLogic): String? { + return logic.dmPath.absolutePath + } +} + +abstract class SdLessDeviceInfo : DeviceInfo { + override val metaonsd = false + override fun isInstalled(logic: DeviceLogic): Boolean { + return SuFile.open(logic.abmSdLessBootsetImg.toURI()).exists() + } + override fun isCorrupt(logic: DeviceLogic): Boolean { + return !SuFile.open(logic.abmDb, "db.conf").exists() + } override fun getAbmSettings(logic: DeviceLogic): String? { if (SuFile.open(bdev).exists()) SDUtils.generateMeta(this)?.let { meta -> diff --git a/app/src/main/java/org/andbootmgr/app/DeviceLogic.kt b/app/src/main/java/org/andbootmgr/app/DeviceLogic.kt index 55322d7d..9cdd8b10 100644 --- a/app/src/main/java/org/andbootmgr/app/DeviceLogic.kt +++ b/app/src/main/java/org/andbootmgr/app/DeviceLogic.kt @@ -16,6 +16,13 @@ class DeviceLogic(private val ctx: Context) { val toolkitDir = File(toolkit.targetPath, "Toolkit") // will occasionally be pruned by OS, but it's fine private val rootTmpDir = File("/data/local/tmp") val abmBootset = File(rootTmpDir, ".abm_bootset") + val abmSdLessBootset = File("/data/abm") + val abmSdLessBootsetImg = File(abmSdLessBootset, "bootset.img") + private val metadata = File("/metadata") + val metadataMap = File(metadata, "bootset.map") + val dmBase = File("/dev/block/mapper") + val dmName = "abmbootset" + val dmPath = File(dmBase, dmName) val abmDb = File(abmBootset, "db") val abmEntries = File(abmDb, "entries") val abmDbConf = File(abmDb, "db.conf") @@ -25,6 +32,7 @@ class DeviceLogic(private val ctx: Context) { val ast = d.getAbmSettings(this) ?: return false val bootsetSu = SuFile.open(abmBootset.toURI()) if (!bootsetSu.exists()) bootsetSu.mkdir() + if (!d.metaonsd && !mapBootset()) return false val result = Shell .cmd("mount $ast ${abmBootset.absolutePath}") .exec() @@ -42,7 +50,7 @@ class DeviceLogic(private val ctx: Context) { mounted = true return true } - fun unmountBootset(): Boolean { + fun unmountBootset(d: DeviceInfo): Boolean { if (!checkMounted()) return true val result = Shell.cmd("umount ${abmBootset.absolutePath}").exec() if (!result.isSuccess) { @@ -56,6 +64,7 @@ class DeviceLogic(private val ctx: Context) { Log.e("ABM_UMOUNT", out) return !mounted } + if (!d.metaonsd) unmapBootset() mounted = false return true } @@ -67,6 +76,21 @@ class DeviceLogic(private val ctx: Context) { } return mounted } + private fun mapBootset(): Boolean { + if (SuFile.open(dmPath.toURI()).exists()) + return true + val tempFile = File(cacheDir, "${System.currentTimeMillis()}.txt") + if (!Shell.cmd(File(toolkitDir, "droidboot_map_to_dm") + .absolutePath + " " + metadataMap.absolutePath + " " + tempFile.absolutePath + ).exec().isSuccess) { + return false + } + return Shell.cmd("dmsetup create $dmName ${tempFile.absolutePath}").exec().isSuccess + } + private fun unmapBootset() { + if (SuFile.open(dmPath.toURI()).exists()) + Shell.cmd("dmsetup remove -f --retry $dmName").exec() + } fun mount(p: SDUtils.Partition): Shell.Job { return Shell.cmd(p.mount()) } diff --git a/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt b/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt index f84feba6..ea43364d 100644 --- a/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt @@ -89,8 +89,8 @@ private fun Start(vm: WizardState) { // shared across DroidBootFlow, UpdateDroidBootFlow, FixDroidBootFlow @Composable -fun LoadDroidBootJson(vm: WizardState, content: @Composable () -> Unit) { - var loading by remember { mutableStateOf(!vm.deviceInfo.isBooted(vm.logic) || vm.deviceInfo.postInstallScript) } +fun LoadDroidBootJson(vm: WizardState, update: Boolean, content: @Composable () -> Unit) { + var loading by remember { mutableStateOf(!vm.deviceInfo.isBooted(vm.logic) || vm.deviceInfo.postInstallScript || update) } var error by remember { mutableStateOf(false) } LaunchedEffect(Unit) { if (!loading) return@LaunchedEffect @@ -101,14 +101,16 @@ fun LoadDroidBootJson(vm: WizardState, content: @Composable () -> Unit) { val json = JSONTokener(jsonText).nextValue() as JSONObject if (BuildConfig.VERSION_CODE < json.getInt("minAppVersion")) throw IllegalStateException("please upgrade app") - if (!vm.deviceInfo.isBooted(vm.logic)) { + if ((!vm.deviceInfo.isBooted(vm.logic) || update) && json.has("bootloader")) { val bl = json.getJSONObject("bootloader") - val url = bl.getString("url") - val sha = bl.getStringOrNull("sha256") - vm.inetAvailable["droidboot"] = WizardState.Downloadable( - url, sha, vm.activity.getString(R.string.droidboot_online) - ) - vm.idNeeded.add("droidboot") + if (!bl.optBoolean("updateOnly", false) || update) { + val url = bl.getString("url") + val sha = bl.getStringOrNull("sha256") + vm.inetAvailable["droidboot"] = WizardState.Downloadable( + url, sha, vm.activity.getString(R.string.droidboot_online) + ) + vm.idNeeded.add("droidboot") + } } if (vm.deviceInfo.postInstallScript) { val i = json.getJSONObject("installScript") @@ -140,7 +142,11 @@ fun LoadDroidBootJson(vm: WizardState, content: @Composable () -> Unit) { @Composable private fun Input(d: DroidBootFlowDataHolder) { - LoadDroidBootJson(d.vm) { + LoadDroidBootJson(d.vm, false) { + if (!d.vm.deviceInfo.isBooted(d.vm.logic) && !d.vm.idNeeded.contains("droidboot")) { + Text(stringResource(R.string.install_bl_first)) + return@LoadDroidBootJson + } Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, @@ -241,7 +247,43 @@ private fun Flash(d: DroidBootFlowDataHolder) { return@WizardTerminalWork } } else { - // TODO provision for sdless + if (!SuFile.open(vm.logic.abmSdLessBootset.toURI()).exists()) { + if (!SuFile.open(vm.logic.abmSdLessBootset.toURI()).mkdir()) { + terminal.add(vm.activity.getString(R.string.term_cant_create_bootset)) + return@WizardTerminalWork + } + } + val bytes = 4L * 1024L * 1024L * 1024L // 4 GB for now + if (!Shell.cmd("fallocate -l $bytes" + + vm.logic.abmSdLessBootsetImg.absolutePath).to(terminal).exec().isSuccess) { + terminal.add(vm.activity.getString(R.string.term_failed_fallocate)) + return@WizardTerminalWork + } + if (!Shell.cmd("uncrypt ${vm.logic.abmSdLessBootsetImg.absolutePath} " + + vm.logic.metadataMap.absolutePath).to(terminal).exec().isSuccess) { + terminal.add(vm.activity.getString(R.string.term_failed_uncrypt)) + return@WizardTerminalWork + } + val tempFile = File(vm.logic.cacheDir, "${System.currentTimeMillis()}.txt") + if (!Shell.cmd(File(vm.logic.toolkitDir, "droidboot_map_to_dm") + .absolutePath + " " + vm.logic.metadataMap.absolutePath + " " + tempFile.absolutePath + ).to(terminal).exec().isSuccess) { + terminal.add(vm.activity.getString(R.string.term_failed_mapconv)) + return@WizardTerminalWork + } + if (SuFile.open(vm.logic.dmPath.toURI()).exists()) { + if (!Shell.cmd("dmsetup remove --retry ${vm.logic.dmName}") + .to(terminal).exec().isSuccess + ) { + terminal.add(vm.activity.getString(R.string.term_failed_unmap)) + return@WizardTerminalWork + } + } + if (!Shell.cmd("dmsetup create ${vm.logic.dmName} ${tempFile.absolutePath}") + .to(terminal).exec().isSuccess) { + terminal.add(vm.activity.getString(R.string.term_failed_map)) + return@WizardTerminalWork + } } if (!vm.logic.mountBootset(vm.deviceInfo)) { @@ -256,14 +298,14 @@ private fun Flash(d: DroidBootFlowDataHolder) { if (!SuFile.open(vm.logic.abmDb.toURI()).exists()) { if (!SuFile.open(vm.logic.abmDb.toURI()).mkdir()) { terminal.add(vm.activity.getString(R.string.term_failed_create_db_dir)) - vm.logic.unmountBootset() + vm.logic.unmountBootset(vm.deviceInfo) return@WizardTerminalWork } } if (!SuFile.open(vm.logic.abmEntries.toURI()).exists()) { if (!SuFile.open(vm.logic.abmEntries.toURI()).mkdir()) { terminal.add(vm.activity.getString(R.string.term_failed_create_entries_dir)) - vm.logic.unmountBootset() + vm.logic.unmountBootset(vm.deviceInfo) return@WizardTerminalWork } } @@ -314,7 +356,7 @@ private fun Flash(d: DroidBootFlowDataHolder) { tmpFile.delete() } terminal.add(vm.activity.getString(R.string.term_success)) - vm.logic.unmountBootset() + vm.logic.unmountBootset(vm.deviceInfo) // TODO prompt user to reboot? } } \ No newline at end of file diff --git a/app/src/main/java/org/andbootmgr/app/FixDroidBootFlow.kt b/app/src/main/java/org/andbootmgr/app/FixDroidBootFlow.kt index 4289d629..e1676b4a 100644 --- a/app/src/main/java/org/andbootmgr/app/FixDroidBootFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/FixDroidBootFlow.kt @@ -11,8 +11,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import com.topjohnwu.superuser.io.SuFile import com.topjohnwu.superuser.io.SuFileInputStream -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext import java.io.File import java.io.IOException @@ -39,7 +37,11 @@ class FixDroidBootFlow: WizardFlow() { @Composable private fun Start(vm: WizardState) { - LoadDroidBootJson(vm) { + LoadDroidBootJson(vm, false) { + if (!vm.deviceInfo.isBooted(vm.logic) && !vm.idNeeded.contains("droidboot")) { + Text(stringResource(R.string.install_bl_first)) + return@LoadDroidBootJson + } LaunchedEffect(Unit) { vm.nextText = vm.activity.getString(R.string.next) vm.onNext = { it.navigate(if (vm.idNeeded.isNotEmpty()) "dload" else "flash") } diff --git a/app/src/main/java/org/andbootmgr/app/MainActivity.kt b/app/src/main/java/org/andbootmgr/app/MainActivity.kt index 17fdcfae..a34f73c2 100644 --- a/app/src/main/java/org/andbootmgr/app/MainActivity.kt +++ b/app/src/main/java/org/andbootmgr/app/MainActivity.kt @@ -137,11 +137,11 @@ class MainActivityState(val activity: MainActivity?) { fun unmountBootset() { defaultCfg.clear() - logic!!.unmountBootset() + logic!!.unmountBootset(deviceInfo!!) } fun remountBootset() { - logic!!.unmountBootset() + logic!!.unmountBootset(deviceInfo!!) logic!!.mountBootset(deviceInfo!!) } } @@ -233,10 +233,6 @@ class MainActivity : ComponentActivity() { if (Shell.cmd("mountpoint -q /data/abm/bootset").exec().isSuccess) { Shell.cmd("umount /data/abm/bootset").exec() } - SuFile.open("/data/abm").let { - if (it.exists()) - Shell.cmd("rm -rf /data/abm").exec() - } SuFile.open(filesDir.parentFile!!, "assets").let { if (it.exists()) Shell.cmd("rm -rf ${filesDir.parentFile!!.resolve("assets").absolutePath}") @@ -246,6 +242,14 @@ class MainActivity : ComponentActivity() { // == temp migration code end == } vm.deviceInfo = di.await() // blocking + // == temp migration code 2 start == + if (vm.deviceInfo!!.metaonsd) launch { + SuFile.open("/data/abm").let { + if (it.exists()) + Shell.cmd("rm -rf /data/abm").exec() + } + } + // == temp migration code 2 end == if (StayAliveService.instance == null) { vm.init() } diff --git a/app/src/main/java/org/andbootmgr/app/Start.kt b/app/src/main/java/org/andbootmgr/app/Start.kt index 4941c686..f06a7d54 100644 --- a/app/src/main/java/org/andbootmgr/app/Start.kt +++ b/app/src/main/java/org/andbootmgr/app/Start.kt @@ -166,7 +166,11 @@ fun Start(vm: MainActivityState) { } else if (!mounted) { Text(stringResource(R.string.cannot_mount), textAlign = TextAlign.Center) } else if (vm.isOk) { - PartTool(vm) + if (vm.deviceInfo!!.metaonsd) { + PartTool(vm) + } else { + BootsetTool(vm) + } } else { Text(stringResource(R.string.invalid), textAlign = TextAlign.Center) Text("metaOnSd:$metaOnSd isOk:${vm.isOk}") @@ -466,7 +470,7 @@ private fun PartTool(vm: MainActivityState) { } } Button(onClick = { - vm.currentWizardFlow = BackupRestoreFlow(p.id) + vm.currentWizardFlow = BackupRestoreFlow(p.id, null) // TODO !metaonsd }) { Text(stringResource(R.string.backupnrestore)) } @@ -830,4 +834,9 @@ private fun PartTool(vm: MainActivityState) { ) } } +} + +@Composable +private fun BootsetTool(vm: MainActivityState) { + Text("insert code here") // TODO !metaonsd } \ No newline at end of file diff --git a/app/src/main/java/org/andbootmgr/app/UpdateDroidBootFlow.kt b/app/src/main/java/org/andbootmgr/app/UpdateDroidBootFlow.kt index df9a162a..4bdc5be1 100644 --- a/app/src/main/java/org/andbootmgr/app/UpdateDroidBootFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/UpdateDroidBootFlow.kt @@ -37,7 +37,7 @@ class UpdateDroidBootFlow: WizardFlow() { @Composable private fun Start(vm: WizardState) { - LoadDroidBootJson(vm) { + LoadDroidBootJson(vm, true) { LaunchedEffect(Unit) { vm.nextText = vm.activity.getString(R.string.next) vm.onNext = { it.navigate(if (vm.idNeeded.isNotEmpty()) "dload" else "flash") } diff --git a/app/src/main/java/org/andbootmgr/app/UpdateFlow.kt b/app/src/main/java/org/andbootmgr/app/UpdateFlow.kt index 1742f312..f6bccd8b 100644 --- a/app/src/main/java/org/andbootmgr/app/UpdateFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/UpdateFlow.kt @@ -210,7 +210,7 @@ private fun Flash(u: UpdateFlowDataHolder) { u.vm.logic.extractToolkit(terminal) u.vm.downloadRemainingFiles(terminal) val sp = u.e!!["xpart"]!!.split(":") - val meta = SDUtils.generateMeta(u.vm.deviceInfo)!! + val meta = SDUtils.generateMeta(u.vm.deviceInfo)!! // TODO !metaonsd Shell.cmd(SDUtils.umsd(meta)).exec() val tmpFile = if (u.vm.idNeeded.contains("_install.sh_")) { u.vm.chosen["_install.sh_"]!!.toFile(u.vm).also { diff --git a/app/src/main/java/org/andbootmgr/app/util/SDUtils.kt b/app/src/main/java/org/andbootmgr/app/util/SDUtils.kt index 01a272ee..f91169e5 100644 --- a/app/src/main/java/org/andbootmgr/app/util/SDUtils.kt +++ b/app/src/main/java/org/andbootmgr/app/util/SDUtils.kt @@ -18,6 +18,7 @@ object SDUtils { } fun generateMeta(deviceInfo: DeviceInfo): SDPartitionMeta? { + if (!deviceInfo.metaonsd) return null val meta: SDPartitionMeta val r = Shell.cmd("printf \"mm:%d:%d\\n\" `stat -c '0x%t 0x%T' ${deviceInfo.bdev}` && sgdisk ${deviceInfo.bdev} --print") @@ -200,7 +201,7 @@ object SDUtils { PartitionType.ADOPTED -> "sm unmount private:${this.major},${this.minor}" PartitionType.RESERVED -> { if (name == "abm_settings") { - // TODO unmount bootset + // Unmounting bootset is handled by DeviceLogic, don't forget to do that "true" } else { "echo 'Warning: Unsure on how to unmount this partition.'" @@ -208,6 +209,7 @@ object SDUtils { } PartitionType.SYSTEM, PartitionType.DATA -> { // TODO rework this when dual android is supported by looking at current os' xpart + // but for that we need to know the current os entry :D "true" } else -> "echo 'Warning: Unsure on how to unmount this partition.'" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a509f457..b72022ba 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -262,4 +262,11 @@ bytes percent How many extra IDs? Currently: %d + -- failed to create bootset dir + -- failed to create bootset.img + -- failed to decrypt bootset.img + -- failed to convert bootset.img map + -- failed to map bootset.img + -- failed to unmap bootset.img + You need to install the bootloader manually first. Please check the ABM wiki for more infos.