Find boot image with MagiskInstaller

Fix #8211
This commit is contained in:
topjohnwu 2024-10-07 16:52:35 -07:00
parent 7188de1205
commit e1b847fbc5
4 changed files with 68 additions and 49 deletions

View File

@ -1,13 +1,18 @@
package com.topjohnwu.magisk.dialog package com.topjohnwu.magisk.dialog
import android.widget.Toast
import androidx.core.os.postDelayed
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.topjohnwu.magisk.core.BuildConfig import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Info import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.R import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.ktx.reboot
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.tasks.MagiskInstaller import com.topjohnwu.magisk.core.tasks.MagiskInstaller
import com.topjohnwu.magisk.events.DialogBuilder import com.topjohnwu.magisk.events.DialogBuilder
import com.topjohnwu.magisk.ui.home.HomeViewModel import com.topjohnwu.magisk.ui.home.HomeViewModel
import com.topjohnwu.magisk.view.MagiskDialog import com.topjohnwu.magisk.view.MagiskDialog
import com.topjohnwu.superuser.internal.UiThreadHandler
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class EnvFixDialog(private val vm: HomeViewModel, private val code: Int) : DialogBuilder { class EnvFixDialog(private val vm: HomeViewModel, private val code: Int) : DialogBuilder {
@ -27,9 +32,15 @@ class EnvFixDialog(private val vm: HomeViewModel, private val code: Int) : Dialo
setCancelable(false) setCancelable(false)
} }
dialog.activity.lifecycleScope.launch { dialog.activity.lifecycleScope.launch {
MagiskInstaller.FixEnv { MagiskInstaller.FixEnv().exec { success ->
dialog.dismiss() dialog.dismiss()
}.exec() context.toast(
if (success) R.string.reboot_delay_toast else R.string.setup_fail,
Toast.LENGTH_LONG
)
if (success)
UiThreadHandler.handler.postDelayed(5000) { reboot() }
}
} }
} }
} }

View File

@ -1,15 +1,17 @@
package com.topjohnwu.magisk.dialog package com.topjohnwu.magisk.dialog
import android.app.ProgressDialog import android.app.ProgressDialog
import android.content.Context
import android.widget.Toast import android.widget.Toast
import androidx.lifecycle.lifecycleScope
import com.topjohnwu.magisk.arch.NavigationActivity import com.topjohnwu.magisk.arch.NavigationActivity
import com.topjohnwu.magisk.arch.UIActivity
import com.topjohnwu.magisk.core.R import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.ktx.toast import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
import com.topjohnwu.magisk.events.DialogBuilder import com.topjohnwu.magisk.events.DialogBuilder
import com.topjohnwu.magisk.ui.flash.FlashFragment import com.topjohnwu.magisk.ui.flash.FlashFragment
import com.topjohnwu.magisk.view.MagiskDialog import com.topjohnwu.magisk.view.MagiskDialog
import com.topjohnwu.superuser.Shell import kotlinx.coroutines.launch
class UninstallDialog : DialogBuilder { class UninstallDialog : DialogBuilder {
@ -19,7 +21,7 @@ class UninstallDialog : DialogBuilder {
setMessage(R.string.uninstall_magisk_msg) setMessage(R.string.uninstall_magisk_msg)
setButton(MagiskDialog.ButtonType.POSITIVE) { setButton(MagiskDialog.ButtonType.POSITIVE) {
text = R.string.restore_img text = R.string.restore_img
onClick { restore(dialog.context) } onClick { restore(dialog.activity) }
} }
setButton(MagiskDialog.ButtonType.NEGATIVE) { setButton(MagiskDialog.ButtonType.NEGATIVE) {
text = R.string.complete_uninstall text = R.string.complete_uninstall
@ -29,18 +31,20 @@ class UninstallDialog : DialogBuilder {
} }
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
private fun restore(context: Context) { private fun restore(activity: UIActivity<*>) {
val dialog = ProgressDialog(context).apply { val dialog = ProgressDialog(activity).apply {
setMessage(context.getString(R.string.restore_img_msg)) setMessage(activity.getString(R.string.restore_img_msg))
show() show()
} }
Shell.cmd("restore_imgs").submit { result -> activity.lifecycleScope.launch {
MagiskInstaller.Restore().exec { success ->
dialog.dismiss() dialog.dismiss()
if (result.isSuccess) { if (success) {
context.toast(R.string.restore_done, Toast.LENGTH_SHORT) activity.toast(R.string.restore_done, Toast.LENGTH_SHORT)
} else { } else {
context.toast(R.string.restore_fail, Toast.LENGTH_LONG) activity.toast(R.string.restore_fail, Toast.LENGTH_LONG)
}
} }
} }
} }

View File

@ -6,7 +6,6 @@ import android.system.ErrnoException
import android.system.Os import android.system.Os
import android.system.OsConstants import android.system.OsConstants
import android.system.OsConstants.O_WRONLY import android.system.OsConstants.O_WRONLY
import android.widget.Toast
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import androidx.core.os.postDelayed import androidx.core.os.postDelayed
import com.topjohnwu.magisk.StubApk import com.topjohnwu.magisk.StubApk
@ -15,13 +14,10 @@ import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.di.ServiceLocator import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.isRunningAsStub import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.ktx.copyAll import com.topjohnwu.magisk.core.ktx.copyAll
import com.topjohnwu.magisk.core.ktx.copyAndClose import com.topjohnwu.magisk.core.ktx.copyAndClose
import com.topjohnwu.magisk.core.ktx.reboot
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.ktx.writeTo import com.topjohnwu.magisk.core.ktx.writeTo
import com.topjohnwu.magisk.core.utils.DummyList import com.topjohnwu.magisk.core.utils.DummyList
import com.topjohnwu.magisk.core.utils.MediaStoreUtils import com.topjohnwu.magisk.core.utils.MediaStoreUtils
@ -585,6 +581,8 @@ abstract class MagiskInstallImpl protected constructor(
protected suspend fun fixEnv() = extractFiles() && "fix_env $installDir".sh().isSuccess protected suspend fun fixEnv() = extractFiles() && "fix_env $installDir".sh().isSuccess
protected fun restore() = findImage() && "restore_imgs $srcBoot".sh().isSuccess
protected fun uninstall() = "run_uninstaller $AppApkPath".sh().isSuccess protected fun uninstall() = "run_uninstaller $AppApkPath".sh().isSuccess
@WorkerThread @WorkerThread
@ -608,11 +606,10 @@ abstract class MagiskInstallImpl protected constructor(
} }
} }
abstract class MagiskInstaller( abstract class ConsoleInstaller(
console: MutableList<String>, console: MutableList<String>,
logs: MutableList<String> logs: MutableList<String>
) : MagiskInstallImpl(console, logs) { ) : MagiskInstallImpl(console, logs) {
override suspend fun exec(): Boolean { override suspend fun exec(): Boolean {
val success = super.exec() val success = super.exec()
if (success) { if (success) {
@ -622,40 +619,51 @@ abstract class MagiskInstaller(
} }
return success return success
} }
}
abstract class CallBackInstaller : MagiskInstallImpl(DummyList, DummyList) {
suspend fun exec(callback: (Boolean) -> Unit): Boolean {
val success = exec()
callback(success)
return success
}
}
class MagiskInstaller {
class Patch( class Patch(
private val uri: Uri, private val uri: Uri,
console: MutableList<String>, console: MutableList<String>,
logs: MutableList<String> logs: MutableList<String>
) : MagiskInstaller(console, logs) { ) : ConsoleInstaller(console, logs) {
override suspend fun operations() = patchFile(uri) override suspend fun operations() = patchFile(uri)
} }
class SecondSlot( class SecondSlot(
console: MutableList<String>, console: MutableList<String>,
logs: MutableList<String> logs: MutableList<String>
) : MagiskInstaller(console, logs) { ) : ConsoleInstaller(console, logs) {
override suspend fun operations() = secondSlot() override suspend fun operations() = secondSlot()
} }
class Direct( class Direct(
console: MutableList<String>, console: MutableList<String>,
logs: MutableList<String> logs: MutableList<String>
) : MagiskInstaller(console, logs) { ) : ConsoleInstaller(console, logs) {
override suspend fun operations() = direct() override suspend fun operations() = direct()
} }
class Emulator( class Emulator(
console: MutableList<String>, console: MutableList<String>,
logs: MutableList<String> logs: MutableList<String>
) : MagiskInstaller(console, logs) { ) : ConsoleInstaller(console, logs) {
override suspend fun operations() = fixEnv() override suspend fun operations() = fixEnv()
} }
class Uninstall( class Uninstall(
console: MutableList<String>, console: MutableList<String>,
logs: MutableList<String> logs: MutableList<String>
) : MagiskInstallImpl(console, logs) { ) : ConsoleInstaller(console, logs) {
override suspend fun operations() = uninstall() override suspend fun operations() = uninstall()
override suspend fun exec(): Boolean { override suspend fun exec(): Boolean {
@ -669,19 +677,11 @@ abstract class MagiskInstaller(
} }
} }
class FixEnv(private val callback: () -> Unit) : MagiskInstallImpl(DummyList, DummyList) { class Restore : CallBackInstaller() {
override suspend fun operations() = fixEnv() override suspend fun operations() = restore()
override suspend fun exec(): Boolean {
val success = super.exec()
callback()
context.toast(
if (success) R.string.reboot_delay_toast else R.string.setup_fail,
Toast.LENGTH_LONG
)
if (success)
UiThreadHandler.handler.postDelayed(5000) { reboot() }
return success
} }
class FixEnv : CallBackInstaller() {
override suspend fun operations() = fixEnv()
} }
} }

View File

@ -2,10 +2,14 @@
# Magisk app internal scripts # Magisk app internal scripts
################################## ##################################
# $1 = delay
# $2 = command
run_delay() { run_delay() {
(sleep $1; $2)& (sleep $1; $2)&
} }
# $1 = version string
# $2 = version code
env_check() { env_check() {
for file in busybox magiskboot magiskinit util_functions.sh boot_patch.sh; do for file in busybox magiskboot magiskinit util_functions.sh boot_patch.sh; do
[ -f "$MAGISKBIN/$file" ] || return 1 [ -f "$MAGISKBIN/$file" ] || return 1
@ -21,6 +25,8 @@ env_check() {
return 0 return 0
} }
# $1 = dir to copy
# $2 = destination (optional)
cp_readlink() { cp_readlink() {
if [ -z $2 ]; then if [ -z $2 ]; then
cd $1 cd $1
@ -39,6 +45,7 @@ cp_readlink() {
cd / cd /
} }
# $1 = install dir
fix_env() { fix_env() {
# Cleanup and make dirs # Cleanup and make dirs
rm -rf $MAGISKBIN/* rm -rf $MAGISKBIN/*
@ -49,6 +56,8 @@ fix_env() {
chown -R 0:0 $MAGISKBIN chown -R 0:0 $MAGISKBIN
} }
# $1 = install dir
# $2 = boot partition
direct_install() { direct_install() {
echo "- Flashing new boot image" echo "- Flashing new boot image"
flash_image $1/new-boot.img $2 flash_image $1/new-boot.img $2
@ -70,6 +79,7 @@ direct_install() {
return 0 return 0
} }
# $1 = uninstaller zip
run_uninstaller() { run_uninstaller() {
rm -rf /dev/tmp rm -rf /dev/tmp
mkdir -p /dev/tmp/install mkdir -p /dev/tmp/install
@ -77,24 +87,16 @@ run_uninstaller() {
INSTALLER=/dev/tmp/install sh /dev/tmp/install/assets/uninstaller.sh dummy 1 "$1" INSTALLER=/dev/tmp/install sh /dev/tmp/install/assets/uninstaller.sh dummy 1 "$1"
} }
# $1 = boot partition
restore_imgs() { restore_imgs() {
local SHA1=$(grep_prop SHA1 $MAGISKTMP/.magisk/config) local SHA1=$(grep_prop SHA1 $MAGISKTMP/.magisk/config)
local BACKUPDIR=/data/magisk_backup_$SHA1 local BACKUPDIR=/data/magisk_backup_$SHA1
[ -d $BACKUPDIR ] || return 1 [ -d $BACKUPDIR ] || return 1
get_flags
find_boot_image
for name in dtb dtbo; do
[ -f $BACKUPDIR/${name}.img.gz ] || continue
local IMAGE=$(find_block $name$SLOT)
[ -z $IMAGE ] && continue
flash_image $BACKUPDIR/${name}.img.gz $IMAGE
done
[ -f $BACKUPDIR/boot.img.gz ] || return 1 [ -f $BACKUPDIR/boot.img.gz ] || return 1
flash_image $BACKUPDIR/boot.img.gz $BOOTIMAGE flash_image $BACKUPDIR/boot.img.gz $1
} }
# $1 = path to bootctl executable
post_ota() { post_ota() {
cd /data/adb cd /data/adb
cp -f $1 bootctl cp -f $1 bootctl
@ -131,6 +133,8 @@ EOF
cd / cd /
} }
# $1 = APK
# $2 = package name
adb_pm_install() { adb_pm_install() {
local tmp=/data/local/tmp/temp.apk local tmp=/data/local/tmp/temp.apk
cp -f "$1" $tmp cp -f "$1" $tmp