diff --git a/app/src/main/java/com/topjohnwu/magisk/core/App.kt b/app/src/main/java/com/topjohnwu/magisk/core/App.kt index 5797f46c1..6d5590078 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/App.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/App.kt @@ -8,6 +8,7 @@ import android.os.Bundle import com.topjohnwu.magisk.StubApk import com.topjohnwu.magisk.core.di.ServiceLocator import com.topjohnwu.magisk.core.utils.DispatcherExecutor +import com.topjohnwu.magisk.core.utils.ProcessLifecycle import com.topjohnwu.magisk.core.utils.RootUtils import com.topjohnwu.magisk.core.utils.ShellInit import com.topjohnwu.magisk.core.utils.refreshLocale @@ -80,7 +81,7 @@ open class App() : Application() { override fun onCreate() { super.onCreate() - ProcessLifecycleAccessor.init(this) + ProcessLifecycle.init(this) } override fun onConfigurationChanged(newConfig: Configuration) { diff --git a/app/src/main/java/com/topjohnwu/magisk/core/di/ServiceLocator.kt b/app/src/main/java/com/topjohnwu/magisk/core/di/ServiceLocator.kt index c5034424e..9ea4e8f45 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/di/ServiceLocator.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/di/ServiceLocator.kt @@ -12,6 +12,7 @@ import com.topjohnwu.magisk.core.data.magiskdb.StringDao import com.topjohnwu.magisk.core.ktx.deviceProtectedContext import com.topjohnwu.magisk.core.repository.LogRepository import com.topjohnwu.magisk.core.repository.NetworkService +import com.topjohnwu.magisk.core.utils.BiometricHelper import io.noties.markwon.Markwon import io.noties.markwon.utils.NoCopySpannableFactory @@ -23,6 +24,7 @@ object ServiceLocator { lateinit var context: Context val deContext by lazy { context.deviceProtectedContext } val timeoutPrefs by lazy { deContext.getSharedPreferences("su_timeout", 0) } + val biometrics by lazy { BiometricHelper(context) } // Database val policyDB = PolicyDao() diff --git a/app/src/main/java/com/topjohnwu/magisk/core/ktx/XAndroid.kt b/app/src/main/java/com/topjohnwu/magisk/core/ktx/XAndroid.kt index 277912da4..354dd9e3a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/ktx/XAndroid.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/ktx/XAndroid.kt @@ -12,7 +12,6 @@ import android.graphics.Canvas import android.graphics.drawable.AdaptiveIconDrawable import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.LayerDrawable -import android.net.Uri import android.os.Build import android.os.Build.VERSION.SDK_INT import android.os.Process @@ -21,16 +20,12 @@ import android.view.inputmethod.InputMethodManager import android.widget.Toast import androidx.appcompat.content.res.AppCompatResources import androidx.core.content.getSystemService -import com.topjohnwu.magisk.core.Const import com.topjohnwu.magisk.core.utils.RootUtils import com.topjohnwu.magisk.core.utils.currentLocale import com.topjohnwu.magisk.utils.APKInstall -import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.internal.UiThreadHandler import java.io.File -import kotlin.Array import kotlin.String -import java.lang.reflect.Array as JArray fun Context.rawResource(id: Int) = resources.openRawResource(id) @@ -56,110 +51,6 @@ val Context.deviceProtectedContext: Context get() = createDeviceProtectedStorageContext() } else { this } -fun Intent.startActivityWithRoot() { - val args = mutableListOf("am", "start", "--user", Const.USER_ID.toString()) - val cmd = toCommand(args).joinToString(" ") - Shell.cmd(cmd).submit() -} - -fun Intent.toCommand(args: MutableList = mutableListOf()): MutableList { - action?.also { - args.add("-a") - args.add(it) - } - component?.also { - args.add("-n") - args.add(it.flattenToString()) - } - data?.also { - args.add("-d") - args.add(it.toString()) - } - categories?.also { - for (cat in it) { - args.add("-c") - args.add(cat) - } - } - type?.also { - args.add("-t") - args.add(it) - } - extras?.also { - loop@ for (key in it.keySet()) { - val v = it[key] ?: continue - var value: Any = v - val arg: String - when { - v is String -> arg = "--es" - v is Boolean -> arg = "--ez" - v is Int -> arg = "--ei" - v is Long -> arg = "--el" - v is Float -> arg = "--ef" - v is Uri -> arg = "--eu" - v is ComponentName -> { - arg = "--ecn" - value = v.flattenToString() - } - v is List<*> -> { - if (v.isEmpty()) - continue@loop - - arg = if (v[0] is Int) - "--eial" - else if (v[0] is Long) - "--elal" - else if (v[0] is Float) - "--efal" - else if (v[0] is String) - "--esal" - else - continue@loop /* Unsupported */ - - val sb = StringBuilder() - for (o in v) { - sb.append(o.toString().replace(",", "\\,")) - sb.append(',') - } - // Remove trailing comma - sb.deleteCharAt(sb.length - 1) - value = sb - } - v.javaClass.isArray -> { - arg = if (v is IntArray) - "--eia" - else if (v is LongArray) - "--ela" - else if (v is FloatArray) - "--efa" - else if (v is Array<*> && v.isArrayOf()) - "--esa" - else - continue@loop /* Unsupported */ - - val sb = StringBuilder() - val len = JArray.getLength(v) - for (i in 0 until len) { - sb.append(JArray.get(v, i)!!.toString().replace(",", "\\,")) - sb.append(',') - } - // Remove trailing comma - sb.deleteCharAt(sb.length - 1) - value = sb - } - else -> continue@loop - } /* Unsupported */ - - args.add(arg) - args.add(key) - args.add(value.toString()) - } - } - args.add("-f") - args.add(flags.toString()) - return args -} - fun Context.cachedFile(name: String) = File(cacheDir, name) fun ApplicationInfo.getLabel(pm: PackageManager): String { diff --git a/app/src/main/java/com/topjohnwu/magisk/core/ktx/XSU.kt b/app/src/main/java/com/topjohnwu/magisk/core/ktx/XSU.kt index d21b9a8da..e6f035f4d 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/ktx/XSU.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/ktx/XSU.kt @@ -1,8 +1,6 @@ package com.topjohnwu.magisk.core.ktx -import android.content.Context import com.topjohnwu.magisk.core.Config -import com.topjohnwu.magisk.core.Const import com.topjohnwu.superuser.Shell import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -15,12 +13,4 @@ fun reboot(reason: String = if (Config.recovery) "recovery" else "") { Shell.cmd("/system/bin/svc power reboot $reason || /system/bin/reboot $reason").submit() } -fun relaunchApp(context: Context) { - val intent = context.packageManager.getLaunchIntentForPackage(context.packageName) ?: return - val args = mutableListOf("am", "start", "--user", Const.USER_ID.toString()) - val cmd = intent.toCommand(args).joinToString(separator = " ") - Shell.cmd("run_delay 1 \"$cmd\"").exec() - Runtime.getRuntime().exit(0) -} - suspend fun Shell.Job.await() = withContext(Dispatchers.IO) { exec() } diff --git a/app/src/main/java/com/topjohnwu/magisk/core/utils/BiometricHelper.kt b/app/src/main/java/com/topjohnwu/magisk/core/utils/BiometricHelper.kt index 073d3514e..52ccb6a99 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/utils/BiometricHelper.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/utils/BiometricHelper.kt @@ -1,18 +1,19 @@ package com.topjohnwu.magisk.core.utils +import android.content.Context import androidx.biometric.BiometricManager +import androidx.biometric.BiometricManager.Authenticators import androidx.biometric.BiometricPrompt import androidx.core.content.ContextCompat import androidx.fragment.app.FragmentActivity import com.topjohnwu.magisk.R import com.topjohnwu.magisk.core.Config -import com.topjohnwu.magisk.core.di.AppContext -object BiometricHelper { +class BiometricHelper(context: Context) { - private val mgr by lazy { BiometricManager.from(AppContext) } + private val mgr = BiometricManager.from(context) - val isSupported get() = when (mgr.canAuthenticate()) { + val isSupported get() = when (mgr.canAuthenticate(Authenticators.BIOMETRIC_WEAK)) { BiometricManager.BIOMETRIC_SUCCESS -> true else -> false } @@ -48,7 +49,7 @@ object BiometricHelper { ) val info = BiometricPrompt.PromptInfo.Builder() .setConfirmationRequired(true) - .setDeviceCredentialAllowed(false) + .setAllowedAuthenticators(Authenticators.BIOMETRIC_WEAK) .setTitle(activity.getString(R.string.authenticate)) .setNegativeButtonText(activity.getString(android.R.string.cancel)) .build() diff --git a/app/src/main/java/com/topjohnwu/magisk/core/ProcessLifecycleAccessor.java b/app/src/main/java/com/topjohnwu/magisk/core/utils/ProcessLifecycle.java similarity index 84% rename from app/src/main/java/com/topjohnwu/magisk/core/ProcessLifecycleAccessor.java rename to app/src/main/java/com/topjohnwu/magisk/core/utils/ProcessLifecycle.java index f0cd7e287..56180b97b 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/ProcessLifecycleAccessor.java +++ b/app/src/main/java/com/topjohnwu/magisk/core/utils/ProcessLifecycle.java @@ -1,4 +1,4 @@ -package com.topjohnwu.magisk.core; +package com.topjohnwu.magisk.core.utils; import android.content.Context; @@ -7,7 +7,7 @@ import androidx.lifecycle.LifecycleDispatcher; import androidx.lifecycle.ProcessLifecycleOwner; // Use Java to bypass Kotlin internal visibility modifier -public class ProcessLifecycleAccessor { +public class ProcessLifecycle { public static void init(@NonNull Context context) { LifecycleDispatcher.init(context); ProcessLifecycleOwner.init$lifecycle_process_release(context); diff --git a/app/src/main/java/com/topjohnwu/magisk/events/BiometricEvent.kt b/app/src/main/java/com/topjohnwu/magisk/events/BiometricEvent.kt index 8cc3f5490..0c81f3816 100644 --- a/app/src/main/java/com/topjohnwu/magisk/events/BiometricEvent.kt +++ b/app/src/main/java/com/topjohnwu/magisk/events/BiometricEvent.kt @@ -3,6 +3,7 @@ package com.topjohnwu.magisk.events import com.topjohnwu.magisk.arch.ActivityExecutor import com.topjohnwu.magisk.arch.UIActivity import com.topjohnwu.magisk.arch.ViewEvent +import com.topjohnwu.magisk.core.di.ServiceLocator import com.topjohnwu.magisk.core.utils.BiometricHelper class BiometricEvent( @@ -17,7 +18,7 @@ class BiometricEvent( } override fun invoke(activity: UIActivity<*>) { - BiometricHelper.authenticate( + ServiceLocator.biometrics.authenticate( activity, onError = listenerOnFailure, onSuccess = listenerOnSuccess diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt index 8cf8ef135..d8410c8fc 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt @@ -12,6 +12,7 @@ import com.topjohnwu.magisk.R import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.Const import com.topjohnwu.magisk.core.Info +import com.topjohnwu.magisk.core.di.ServiceLocator import com.topjohnwu.magisk.core.ktx.activity import com.topjohnwu.magisk.core.tasks.HideAPK import com.topjohnwu.magisk.core.utils.BiometricHelper @@ -289,7 +290,7 @@ object Biometrics : BaseSettingsItem.Toggle() { override var value by Config::suBiometric override fun refresh() { - isEnabled = BiometricHelper.isSupported + isEnabled = ServiceLocator.biometrics.isSupported if (!isEnabled) { value = false description = R.string.no_biometric.asText() diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/superuser/SuperuserViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/superuser/SuperuserViewModel.kt index 06c91af8c..958243159 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/superuser/SuperuserViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/superuser/SuperuserViewModel.kt @@ -13,6 +13,7 @@ import com.topjohnwu.magisk.arch.AsyncLoadViewModel import com.topjohnwu.magisk.core.Info import com.topjohnwu.magisk.core.data.magiskdb.PolicyDao import com.topjohnwu.magisk.core.di.AppContext +import com.topjohnwu.magisk.core.di.ServiceLocator import com.topjohnwu.magisk.core.ktx.getLabel import com.topjohnwu.magisk.core.model.su.SuPolicy import com.topjohnwu.magisk.core.utils.BiometricHelper @@ -113,7 +114,7 @@ class SuperuserViewModel( } } - if (BiometricHelper.isEnabled) { + if (ServiceLocator.biometrics.isEnabled) { BiometricEvent { onSuccess { updateState() } }.publish() @@ -169,7 +170,7 @@ class SuperuserViewModel( } } - if (BiometricHelper.isEnabled) { + if (ServiceLocator.biometrics.isEnabled) { BiometricEvent { onSuccess { updateState() } }.publish() diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestViewModel.kt index fd4103208..322dfcb31 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestViewModel.kt @@ -22,6 +22,7 @@ import com.topjohnwu.magisk.arch.BaseViewModel import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.data.magiskdb.PolicyDao import com.topjohnwu.magisk.core.di.AppContext +import com.topjohnwu.magisk.core.di.ServiceLocator import com.topjohnwu.magisk.core.ktx.getLabel import com.topjohnwu.magisk.core.ktx.toast import com.topjohnwu.magisk.core.model.su.SuPolicy.Companion.ALLOW @@ -75,7 +76,7 @@ class SuRequestViewModel( fun grantPressed() { cancelTimer() - if (BiometricHelper.isEnabled) { + if (ServiceLocator.biometrics.isEnabled) { BiometricEvent { onSuccess { respond(ALLOW)