diff --git a/app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt b/app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt index 861f1ce27..f58961dda 100644 --- a/app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt +++ b/app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt @@ -9,12 +9,11 @@ import org.koin.dsl.module val applicationModule = module { single { RxBus() } - single { get().resources } - single { get() as App } - single { get().packageManager } + factory { get().resources } + factory { get() as App } + factory { get().packageManager } single(SUTimeout) { - get().protectedContext - .getSharedPreferences("su_timeout", 0) + get().protectedContext.getSharedPreferences("su_timeout", 0) } single { PreferenceManager.getDefaultSharedPreferences(get().protectedContext) } } diff --git a/app/src/main/java/com/topjohnwu/magisk/di/ViewModelsModule.kt b/app/src/main/java/com/topjohnwu/magisk/di/ViewModelsModule.kt index 8b0f22d4c..9983734a8 100644 --- a/app/src/main/java/com/topjohnwu/magisk/di/ViewModelsModule.kt +++ b/app/src/main/java/com/topjohnwu/magisk/di/ViewModelsModule.kt @@ -15,7 +15,7 @@ import org.koin.dsl.module val viewModelModules = module { viewModel { MainViewModel() } - viewModel { HomeViewModel(get(), get(), get()) } + viewModel { HomeViewModel(get(), get()) } viewModel { SuperuserViewModel(get(), get(), get(), get()) } viewModel { HideViewModel(get(), get()) } viewModel { ModuleViewModel(get(), get()) } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskActivity.kt b/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskActivity.kt index 20384d02f..ec0a1f4d6 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskActivity.kt @@ -1,6 +1,7 @@ package com.topjohnwu.magisk.ui.base import android.content.Intent +import android.content.res.Configuration import android.os.Bundle import androidx.annotation.CallSuper import androidx.appcompat.app.AppCompatDelegate @@ -24,6 +25,7 @@ import com.topjohnwu.magisk.model.navigation.MagiskAnimBuilder import com.topjohnwu.magisk.model.navigation.MagiskNavigationEvent import com.topjohnwu.magisk.model.navigation.Navigator import com.topjohnwu.magisk.model.permissions.PermissionRequestBuilder +import com.topjohnwu.magisk.utils.LocaleManager import com.topjohnwu.magisk.utils.Utils import timber.log.Timber import kotlin.reflect.KClass @@ -58,6 +60,12 @@ abstract class MagiskActivity TODO() - MagiskState.NOT_INSTALLED -> resources.getString(R.string.magisk_version_error) - MagiskState.UP_TO_DATE -> resources.getString(R.string.magisk_up_to_date) - MagiskState.LOADING -> resources.getString(R.string.checking_for_updates) - MagiskState.OBSOLETE -> resources.getString(R.string.magisk_update_title) + MagiskState.NOT_INSTALLED -> R.string.magisk_version_error.res() + MagiskState.UP_TO_DATE -> R.string.magisk_up_to_date.res() + MagiskState.LOADING -> R.string.checking_for_updates.res() + MagiskState.OBSOLETE -> R.string.magisk_update_title.res() } } val magiskCurrentVersion = KObservableField("") val magiskLatestVersion = KObservableField("") val magiskAdditionalInfo = Observer(magiskState) { if (Config.get(Config.Key.COREONLY)) - resources.getString(R.string.core_only_enabled) + R.string.core_only_enabled.res() else "" } @@ -49,22 +54,22 @@ class HomeViewModel( val managerStateText = Observer(managerState) { when (managerState.value) { MagiskState.NO_ROOT -> "wtf" - MagiskState.NOT_INSTALLED -> resources.getString(R.string.invalid_update_channel) - MagiskState.UP_TO_DATE -> resources.getString(R.string.manager_up_to_date) - MagiskState.LOADING -> resources.getString(R.string.checking_for_updates) - MagiskState.OBSOLETE -> resources.getString(R.string.manager_update_title) + MagiskState.NOT_INSTALLED -> R.string.invalid_update_channel.res() + MagiskState.UP_TO_DATE -> R.string.manager_up_to_date.res() + MagiskState.LOADING -> R.string.checking_for_updates.res() + MagiskState.OBSOLETE -> R.string.manager_update_title.res() } } val managerCurrentVersion = KObservableField("") val managerLatestVersion = KObservableField("") val managerAdditionalInfo = Observer(managerState) { - if (app.packageName != BuildConfig.APPLICATION_ID) - "(${app.packageName})" + if (packageName != BuildConfig.APPLICATION_ID) + "($packageName)" else "" } - val safetyNetTitle = KObservableField(resources.getString(R.string.safetyNet_check_text)) + val safetyNetTitle = KObservableField(R.string.safetyNet_check_text.res()) val ctsState = KObservableField(SafetyNetState.IDLE) val basicIntegrityState = KObservableField(SafetyNetState.IDLE) val safetyNetState = Observer(ctsState, basicIntegrityState) { @@ -82,8 +87,6 @@ class HomeViewModel( val hasRoot = KObservableField(false) private var shownDialog = false - private val current = resources.getString(R.string.current_installed) - private val latest = resources.getString(R.string.latest_version) init { isForceEncryption.addOnPropertyChangedCallback { @@ -118,7 +121,7 @@ class HomeViewModel( fun safetyNetPressed() { ctsState.value = SafetyNetState.LOADING basicIntegrityState.value = SafetyNetState.LOADING - safetyNetTitle.value = resources.getString(R.string.checking_safetyNet_status) + safetyNetTitle.value = R.string.checking_safetyNet_status.res() UpdateSafetyNetEvent().publish() } @@ -127,7 +130,7 @@ class HomeViewModel( response and 0x0F == 0 -> { val hasCtsPassed = response and ISafetyNetHelper.CTS_PASS != 0 val hasBasicIntegrityPassed = response and ISafetyNetHelper.BASIC_PASS != 0 - safetyNetTitle.value = resources.getString(R.string.safetyNet_check_success) + safetyNetTitle.value = R.string.safetyNet_check_success.res() ctsState.value = if (hasCtsPassed) { SafetyNetState.PASS } else { @@ -146,11 +149,10 @@ class HomeViewModel( else -> { ctsState.value = SafetyNetState.IDLE basicIntegrityState.value = SafetyNetState.IDLE - val errorString = when (response) { + safetyNetTitle.value = when (response) { ISafetyNetHelper.RESPONSE_ERR -> R.string.safetyNet_res_invalid else -> R.string.safetyNet_api_error - } - safetyNetTitle.value = resources.getString(errorString) + }.res() } } @@ -185,16 +187,14 @@ class HomeViewModel( else -> MagiskState.UP_TO_DATE } - if (magiskState.value != MagiskState.NOT_INSTALLED) { - magiskCurrentVersion.value = version - .format(Config.magiskVersionString, Config.magiskVersionCode) - .let { current.format(it) } + magiskCurrentVersion.value = if (magiskState.value != MagiskState.NOT_INSTALLED) { + version.format(Config.magiskVersionString, Config.magiskVersionCode) } else { - magiskCurrentVersion.value = "" + "" } + magiskLatestVersion.value = version .format(Config.remoteMagiskVersionString, Config.remoteMagiskVersionCode) - .let { latest.format(it) } managerState.value = when (Config.remoteManagerVersionCode) { in Int.MIN_VALUE until 0 -> MagiskState.NOT_INSTALLED //wrong update channel @@ -204,10 +204,9 @@ class HomeViewModel( managerCurrentVersion.value = version .format(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE) - .let { current.format(it) } + managerLatestVersion.value = version .format(Config.remoteManagerVersionString, Config.remoteManagerVersionCode) - .let { latest.format(it) } } private fun ensureEnv() { diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/XAndroid.kt b/app/src/main/java/com/topjohnwu/magisk/utils/XAndroid.kt index 2aed7516a..97acddf5f 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/XAndroid.kt +++ b/app/src/main/java/com/topjohnwu/magisk/utils/XAndroid.kt @@ -13,6 +13,12 @@ import com.topjohnwu.magisk.App import java.io.File import java.io.FileNotFoundException +val packageName: String + get() { + val app: App by inject() + return app.packageName + } + val PackageInfo.processes get() = activities?.processNames.orEmpty() + services?.processNames.orEmpty() + diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/XString.kt b/app/src/main/java/com/topjohnwu/magisk/utils/XString.kt index 874eb8bab..3551d6c60 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/XString.kt +++ b/app/src/main/java/com/topjohnwu/magisk/utils/XString.kt @@ -1,5 +1,7 @@ package com.topjohnwu.magisk.utils +import android.content.res.Resources + val specialChars = arrayOf('!', '@', '#', '$', '%', '&', '?') fun String.replaceRandomWithSpecial(): String { @@ -11,4 +13,9 @@ fun String.replaceRandomWithSpecial(): String { } fun StringBuilder.appendIf(condition: Boolean, builder: StringBuilder.() -> Unit) = - if (condition) apply(builder) else this \ No newline at end of file + if (condition) apply(builder) else this + +fun Int.res(vararg args: Any): String { + val resources: Resources by inject() + return resources.getString(this, *args) +} \ No newline at end of file diff --git a/app/src/main/res/layout/include_update_card.xml b/app/src/main/res/layout/include_update_card.xml index a337a0edf..c40b531ac 100644 --- a/app/src/main/res/layout/include_update_card.xml +++ b/app/src/main/res/layout/include_update_card.xml @@ -110,7 +110,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:maxLines="1" - android:text="@{state != MagiskState.LOADING ? currentVersion : @string/checking_for_updates}" + android:text="@{state != MagiskState.LOADING ? @string/current_installed(currentVersion) : @string/checking_for_updates}" app:autoSizeMinTextSize="1sp" app:autoSizeTextType="uniform" app:layout_constraintBottom_toTopOf="@+id/latest_version" @@ -125,7 +125,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:maxLines="1" - android:text="@{state != MagiskState.LOADING ? latestVersion : @string/checking_for_updates}" + android:text="@{state != MagiskState.LOADING ? @string/latest_version(latestVersion) : @string/checking_for_updates}" app:autoSizeMinTextSize="1sp" app:autoSizeTextType="uniform" app:layout_constraintBottom_toTopOf="@+id/additional" diff --git a/app/src/main/res/raw/utils.sh b/app/src/main/res/raw/utils.sh index 66d2cafe1..4e2a298a1 100644 --- a/app/src/main/res/raw/utils.sh +++ b/app/src/main/res/raw/utils.sh @@ -55,6 +55,7 @@ restore_imgs() { local STOCKDTBO=/data/stock_dtbo.img.gz [ -f $STOCKBOOT ] || return 1 + get_flags find_boot_image find_dtbo_image diff --git a/build.gradle b/build.gradle index d1c94dc2b..ead6ba1b2 100644 --- a/build.gradle +++ b/build.gradle @@ -46,7 +46,7 @@ subprojects { getPlugins().hasPlugin('com.android.application')) { android { compileSdkVersion 'android-Q' - buildToolsVersion '29.0.0-rc2' + buildToolsVersion '29.0.0-rc3' defaultConfig { if (minSdkVersion == null) diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp index 84bd15e9f..36181811e 100644 --- a/native/jni/core/bootstages.cpp +++ b/native/jni/core/bootstages.cpp @@ -374,7 +374,7 @@ static bool magisk_env() { mount_mirror(system, MS_RDONLY); } else if (str_contains(line, " /vendor ")) { mount_mirror(vendor, MS_RDONLY); - } else if (str_contains(line, " /data ")) { + } else if (str_contains(line, " /data ") && !str_contains(line, "tmpfs")) { mount_mirror(data, 0); } else if (SDK_INT >= 24 && str_contains(line, " /proc ") && !str_contains(line, "hidepid=2")) { diff --git a/native/jni/magiskboot/main.cpp b/native/jni/magiskboot/main.cpp index e9d6eb217..545a01e82 100644 --- a/native/jni/magiskboot/main.cpp +++ b/native/jni/magiskboot/main.cpp @@ -74,7 +74,7 @@ static void usage(char *arg0) { " test\n" " Check if fstab has verity/avb flags\n" " Return values:\n" - " 0:no flags 1:flag exists\n" + " 0:flag exists 1:no flags\n" " patch\n" " Search for fstab and remove verity/avb\n" "\n" diff --git a/scripts/magisk_uninstaller.sh b/scripts/magisk_uninstaller.sh index 8a9fd2410..0fb59b9ff 100644 --- a/scripts/magisk_uninstaller.sh +++ b/scripts/magisk_uninstaller.sh @@ -55,6 +55,7 @@ $BOOTMODE || recovery_actions # Uninstall ########################################################################################## +get_flags find_boot_image find_dtbo_image @@ -67,36 +68,35 @@ cd $MAGISKBIN CHROMEOS=false ui_print "- Unpacking boot image" -./magiskboot --unpack "$BOOTIMAGE" +./magiskboot unpack "$BOOTIMAGE" case $? in 1 ) - abort "! Unable to unpack boot image" + abort "! Unsupported/Unknown image format" ;; 2 ) ui_print "- ChromeOS boot image detected" CHROMEOS=true ;; - 3 ) - ui_print "! Sony ELF32 format detected" - abort "! Please use BootBridge from @AdrianDC" - ;; - 4 ) - ui_print "! Sony ELF64 format detected" - abort "! Stock kernel cannot be patched, please use a custom kernel" esac # Detect boot image state ui_print "- Checking ramdisk status" -./magiskboot --cpio ramdisk.cpio test -case $? in +if [ -e ramdisk.cpio ]; then + ./magiskboot cpio ramdisk.cpio test + STATUS=$? +else + # Stock A only system-as-root + STATUS=0 +fi +case $((STATUS & 3)) in 0 ) # Stock boot ui_print "- Stock boot image detected" ;; 1 ) # Magisk patched ui_print "- Magisk patched image detected" # Find SHA1 of stock boot image - [ -z $SHA1 ] && SHA1=`./magiskboot --cpio ramdisk.cpio sha1 2>/dev/null` + [ -z $SHA1 ] && SHA1=`./magiskboot cpio ramdisk.cpio sha1 2>/dev/null` STOCKBOOT=/data/stock_boot_${SHA1}.img.gz STOCKDTBO=/data/stock_dtbo.img.gz if [ -f $STOCKBOOT ]; then @@ -109,16 +109,20 @@ case $? in else ui_print "! Boot image backup unavailable" ui_print "- Restoring ramdisk with internal backup" - ./magiskboot --cpio ramdisk.cpio restore - ./magiskboot --repack $BOOTIMAGE + ./magiskboot cpio ramdisk.cpio restore + if ! ./magiskboot cpio ramdisk.cpio "exists init.rc"; then + # A only system-as-root + rm -f ramdisk.cpio + fi + ./magiskboot repack $BOOTIMAGE # Sign chromeos boot $CHROMEOS && sign_chromeos ui_print "- Flashing restored boot image" flash_image new-boot.img $BOOTIMAGE || abort "! Insufficient partition size" fi ;; - 2 ) # Other patched - ui_print "! Boot image patched by other programs" + 2 ) # Unsupported + ui_print "! Boot image patched by unsupported programs" abort "! Cannot uninstall" ;; esac