diff --git a/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt b/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt index 206c5cca..c00acf4d 100644 --- a/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt @@ -993,7 +993,7 @@ private fun Flash(c: CreatePartDataHolder) { (BigDecimal(c.p.size - (offset + c.f)).multiply(BigDecimal(b).divide(BigDecimal(100)))).toLong() } - vm.logic.unmount(vm.deviceInfo!!) + vm.logic.unmountBootset() val r = Shell.cmd(SDUtils.umsd(c.meta!!) + " && " + c.p.create(offset, offset + k, code, "")).to(terminal).exec() try { if (r.out.join("\n").contains("kpartx")) { @@ -1011,7 +1011,7 @@ private fun Flash(c: CreatePartDataHolder) { makeOne(it + 1) } else { terminal.add(vm.activity.getString(R.string.term_created_pt)) - vm.logic.mount(vm.deviceInfo) + vm.logic.mountBootset(vm.deviceInfo) installMore() } } else { diff --git a/app/src/main/java/org/andbootmgr/app/DeviceInfo.kt b/app/src/main/java/org/andbootmgr/app/DeviceInfo.kt index 36ae523a..74597b2d 100644 --- a/app/src/main/java/org/andbootmgr/app/DeviceInfo.kt +++ b/app/src/main/java/org/andbootmgr/app/DeviceInfo.kt @@ -31,10 +31,11 @@ interface DeviceInfo { } catch (e: Exception) { e.printStackTrace() } - val result = Shell.cmd(File(logic.assetDir, "Scripts/is_installed.sh").absolutePath).exec() + val result = Shell.cmd("grep ABM.bootloader=1 /proc/cmdline").exec() return result.isSuccess && result.out.join("\n").contains("ABM.bootloader=1") } fun isCorrupt(logic: DeviceLogic): Boolean + fun getAbmSettings(logic: DeviceLogic): String? } abstract class MetaOnSdDeviceInfo : DeviceInfo { @@ -49,6 +50,17 @@ abstract class MetaOnSdDeviceInfo : DeviceInfo { 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(bdev, pbdev)?.let { meta -> + if (meta.countPartitions() > 0) { + val part = meta.dumpPartition(0) + if (part.type == SDUtils.PartitionType.RESERVED) + return pbdev + part.id + } + } + return null + } } object HardcodedDeviceInfoFactory { diff --git a/app/src/main/java/org/andbootmgr/app/DeviceLogic.kt b/app/src/main/java/org/andbootmgr/app/DeviceLogic.kt index f8cdfb92..bd1f543b 100644 --- a/app/src/main/java/org/andbootmgr/app/DeviceLogic.kt +++ b/app/src/main/java/org/andbootmgr/app/DeviceLogic.kt @@ -3,65 +3,76 @@ package org.andbootmgr.app import android.content.Context import android.util.Log import com.topjohnwu.superuser.Shell -import com.topjohnwu.superuser.io.SuFile +import org.andbootmgr.app.util.SDUtils import java.io.File class DeviceLogic(ctx: Context) { - val rootDir = ctx.filesDir.parentFile!! + private val rootDir = ctx.filesDir.parentFile!! val assetDir = File(rootDir, "assets") val fileDir = File(rootDir, "files") val cacheDir = File(rootDir, "cache") - val abmDir = File("/data/abm/") - val abmBootset = File(abmDir, "bootset") + val abmBootset = File(fileDir, "bootset") val abmDb = File(abmBootset, "db") val abmEntries = File(abmDb, "entries") var mounted = false - fun mount(d: DeviceInfo): Boolean { - if (mounted) - return true - if (SuFile.open(abmDb.toURI()).exists()) { - mounted = true - return true + fun mountBootset(d: DeviceInfo): Boolean { + when (val code = Shell.cmd("mountpoint -q ${abmBootset.absolutePath}").exec().code) { + 0 -> { + mounted = true + return true + } + 1 -> mounted = false + else -> throw IllegalStateException("mountpoint returned exit code $code, expected 0 or 1") } - val result: Shell.Result = Shell - .cmd(assetDir.absolutePath + "/Scripts/config/mount/" + d.codename + ".sh") + val ast = d.getAbmSettings(this) ?: return false + val result = Shell + .cmd("mount $ast ${abmBootset.absolutePath}") .exec() if (!result.isSuccess) { - val out = result.out.join("\n") - val err = result.err.join("\n") - if (err.contains("Device or resource busy")) { + val out = result.out.join("\n") + result.err.join("\n") + if (out.contains("Device or resource busy")) { mounted = false } - if (err.contains("Invalid argument")) { + if (out.contains("Invalid argument")) { mounted = false } - Log.e("ABM_MOUNT_out", out) - Log.e("ABM_MOUNT_err", err) + Log.e("ABM_MOUNT", out) return mounted } mounted = true return true } - fun unmount(d: DeviceInfo): Boolean { - //if (!mounted) - //return true - val result: Shell.Result = Shell - .cmd(assetDir.absolutePath + "/Scripts/config/umount/" + d.codename + ".sh") - .exec() + fun unmountBootset(): Boolean { + when (val code = Shell.cmd("mountpoint -q ${abmBootset.absolutePath}").exec().code) { + 0 -> mounted = true + 1 -> { + mounted = false + return true + } + else -> throw IllegalStateException("mountpoint returned exit code $code, expected 0 or 1") + } + val result = Shell.cmd("umount ${abmBootset.absolutePath}").exec() if (!result.isSuccess) { - val out = result.out.join("\n") - val err = result.err.join("\n") - if (err.contains("Device or resource busy")) { + val out = result.out.join("\n") + result.err.join("\n") + if (out.contains("Device or resource busy")) { mounted = true } - if (err.contains("Invalid argument")) { + if (out.contains("Invalid argument")) { mounted = false } - Log.e("ABM_UMOUNT_out", out) - Log.e("ABM_UMOUNT_err", err) + Log.e("ABM_UMOUNT", out) return !mounted } mounted = false return true } + fun mount(p: SDUtils.Partition): Shell.Job { + return Shell.cmd(p.mount()) + } + fun unmount(p: SDUtils.Partition): Shell.Job { + return Shell.cmd(p.unmount()) + } + fun delete(p: SDUtils.Partition): Shell.Job { + return Shell.cmd(SDUtils.umsd(p.meta) + " && " + p.delete()) + } } \ No newline at end of file diff --git a/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt b/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt index 35c174a1..6ec46733 100644 --- a/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt @@ -20,7 +20,6 @@ import androidx.compose.ui.unit.dp import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.io.SuFile import com.topjohnwu.superuser.io.SuFileInputStream -import com.topjohnwu.superuser.io.SuFileOutputStream import org.andbootmgr.app.util.AbmTheme import org.andbootmgr.app.util.ConfigFile import org.andbootmgr.app.util.SDUtils @@ -228,7 +227,7 @@ private fun Flash(vm: WizardActivityState) { // TODO provision for sdless } - if (!vm.logic.mount(vm.deviceInfo)) { + if (!vm.logic.mountBootset(vm.deviceInfo)) { terminal.add(vm.activity.getString(R.string.term_failed_mount)) return@Terminal } @@ -240,14 +239,14 @@ private fun Flash(vm: WizardActivityState) { 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.unmount(vm.deviceInfo) + vm.logic.unmountBootset() return@Terminal } } 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.unmount(vm.deviceInfo) + vm.logic.unmountBootset() return@Terminal } } @@ -294,7 +293,7 @@ private fun Flash(vm: WizardActivityState) { ).to(terminal).exec() } terminal.add(vm.activity.getString(R.string.term_success)) - vm.logic.unmount(vm.deviceInfo) + vm.logic.unmountBootset() vm.activity.runOnUiThread { vm.btnsOverride = true vm.nextText.value = vm.activity.getString(R.string.finish) diff --git a/app/src/main/java/org/andbootmgr/app/MainActivity.kt b/app/src/main/java/org/andbootmgr/app/MainActivity.kt index 5c1cba62..64855313 100644 --- a/app/src/main/java/org/andbootmgr/app/MainActivity.kt +++ b/app/src/main/java/org/andbootmgr/app/MainActivity.kt @@ -37,7 +37,6 @@ import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell.FLAG_MOUNT_MASTER import com.topjohnwu.superuser.Shell.FLAG_REDIRECT_STDERR import com.topjohnwu.superuser.io.SuFile -import com.topjohnwu.superuser.io.SuFileInputStream import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.andbootmgr.app.util.AbmTheme @@ -45,7 +44,6 @@ import org.andbootmgr.app.util.ConfigFile import org.andbootmgr.app.util.SDUtils import org.andbootmgr.app.util.Toolkit import java.io.File -import java.io.IOException import java.util.stream.Collectors class MainActivityState { @@ -149,7 +147,7 @@ class MainActivity : ComponentActivity() { vm.root = shell.isRoot vm.deviceInfo = HardcodedDeviceInfoFactory.get(Build.DEVICE) if (vm.deviceInfo != null && vm.deviceInfo!!.isInstalled(vm.logic!!)) { - vm.logic!!.mount(vm.deviceInfo!!) + vm.logic!!.mountBootset(vm.deviceInfo!!) } if (vm.deviceInfo != null) { vm.isOk = ((vm.deviceInfo!!.isInstalled(vm.logic!!)) && @@ -677,7 +675,7 @@ private fun PartTool(vm: MainActivityState) { Row { Button(onClick = { processing = true - Shell.cmd(p.mount()).submit { + vm.logic!!.mount(p).submit { processing = false result = it.out.join("\n") + it.err.join("\n") } @@ -686,7 +684,7 @@ private fun PartTool(vm: MainActivityState) { } Button(onClick = { processing = true - Shell.cmd(p.unmount()).submit { + vm.logic!!.unmount(p).submit { processing = false result = it.out.join("\n") + it.err.join("\n") } @@ -777,9 +775,9 @@ private fun PartTool(vm: MainActivityState) { Button(onClick = { processing = true delete = false - vm.logic!!.unmount(vm.deviceInfo!!) - Shell.cmd(SDUtils.umsd(parts!!) + " && " + p.delete()).submit { - vm.logic!!.mount(vm.deviceInfo!!) + vm.logic!!.unmountBootset() + vm.logic!!.delete(p).submit { + vm.logic!!.mountBootset(vm.deviceInfo!!) processing = false editPartID = null parts = @@ -1011,7 +1009,7 @@ private fun PartTool(vm: MainActivityState) { .map { it.delete() }.collect( Collectors.toList() ) - vm.logic!!.unmount(vm.deviceInfo!!) + vm.logic!!.unmountBootset() for (s in allp) { // Do not chain, but regenerate meta and unmount every time. Thanks void val r = Shell.cmd( SDUtils.umsd(parts!!) + " && " + s @@ -1020,7 +1018,7 @@ private fun PartTool(vm: MainActivityState) { SDUtils.generateMeta(vm.deviceInfo!!.bdev, vm.deviceInfo!!.pbdev) tresult += r.out.join("\n") + r.err.join("\n") + "\n" } - vm.logic!!.mount(vm.deviceInfo!!) + vm.logic!!.mountBootset(vm.deviceInfo!!) } val f = entries[e]!! val f2 = SuFile(vm.logic!!.abmBootset, f.nameWithoutExtension)