mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-02-26 06:37:23 +00:00
Fix su request auto response
This commit is contained in:
parent
d7f7508fa2
commit
b510dc51ac
@ -18,17 +18,16 @@ import java.io.*
|
|||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import java.util.concurrent.TimeUnit.SECONDS
|
import java.util.concurrent.TimeUnit.SECONDS
|
||||||
|
|
||||||
abstract class SuRequestHandler(
|
class SuRequestHandler(
|
||||||
private val packageManager: PackageManager,
|
private val pm: PackageManager,
|
||||||
private val policyDB: PolicyDao
|
private val policyDB: PolicyDao
|
||||||
) : Closeable {
|
) : Closeable {
|
||||||
|
|
||||||
private lateinit var output: DataOutputStream
|
private lateinit var output: DataOutputStream
|
||||||
protected lateinit var policy: SuPolicy
|
lateinit var policy: SuPolicy
|
||||||
private set
|
private set
|
||||||
|
|
||||||
abstract fun onStart()
|
// Return true to indicate undetermined policy, require user interaction
|
||||||
|
|
||||||
suspend fun start(intent: Intent): Boolean {
|
suspend fun start(intent: Intent): Boolean {
|
||||||
if (!init(intent))
|
if (!init(intent))
|
||||||
return false
|
return false
|
||||||
@ -40,15 +39,14 @@ abstract class SuRequestHandler(
|
|||||||
when (Config.suAutoReponse) {
|
when (Config.suAutoReponse) {
|
||||||
Config.Value.SU_AUTO_DENY -> {
|
Config.Value.SU_AUTO_DENY -> {
|
||||||
respond(SuPolicy.DENY, 0)
|
respond(SuPolicy.DENY, 0)
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
Config.Value.SU_AUTO_ALLOW -> {
|
Config.Value.SU_AUTO_ALLOW -> {
|
||||||
respond(SuPolicy.ALLOW, 0)
|
respond(SuPolicy.ALLOW, 0)
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onStart()
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +80,7 @@ abstract class SuRequestHandler(
|
|||||||
val map = async { input.readRequest() }.timedAwait() ?: throw SuRequestError()
|
val map = async { input.readRequest() }.timedAwait() ?: throw SuRequestError()
|
||||||
uid = map["uid"]?.toIntOrNull() ?: throw SuRequestError()
|
uid = map["uid"]?.toIntOrNull() ?: throw SuRequestError()
|
||||||
}
|
}
|
||||||
policy = uid.toPolicy(packageManager)
|
policy = uid.toPolicy(pm)
|
||||||
true
|
true
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
when (e) {
|
when (e) {
|
||||||
|
@ -5,7 +5,7 @@ import com.topjohnwu.magisk.arch.BaseUIActivity
|
|||||||
import com.topjohnwu.magisk.arch.ViewEvent
|
import com.topjohnwu.magisk.arch.ViewEvent
|
||||||
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
||||||
|
|
||||||
class BiometricDialog(
|
class BiometricEvent(
|
||||||
builder: Builder.() -> Unit
|
builder: Builder.() -> Unit
|
||||||
) : ViewEvent(), ActivityExecutor {
|
) : ViewEvent(), ActivityExecutor {
|
||||||
|
|
@ -23,7 +23,7 @@ import com.topjohnwu.magisk.core.tasks.PatchAPK
|
|||||||
import com.topjohnwu.magisk.data.database.RepoDao
|
import com.topjohnwu.magisk.data.database.RepoDao
|
||||||
import com.topjohnwu.magisk.events.AddHomeIconEvent
|
import com.topjohnwu.magisk.events.AddHomeIconEvent
|
||||||
import com.topjohnwu.magisk.events.RecreateEvent
|
import com.topjohnwu.magisk.events.RecreateEvent
|
||||||
import com.topjohnwu.magisk.events.dialog.BiometricDialog
|
import com.topjohnwu.magisk.events.dialog.BiometricEvent
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
import com.topjohnwu.magisk.utils.Utils
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -125,7 +125,7 @@ class SettingsViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun authenticate(callback: () -> Unit) {
|
private fun authenticate(callback: () -> Unit) {
|
||||||
BiometricDialog {
|
BiometricEvent {
|
||||||
// allow the change on success
|
// allow the change on success
|
||||||
onSuccess { callback() }
|
onSuccess { callback() }
|
||||||
}.publish()
|
}.publish()
|
||||||
|
@ -16,7 +16,7 @@ import com.topjohnwu.magisk.core.utils.BiometricHelper
|
|||||||
import com.topjohnwu.magisk.core.utils.currentLocale
|
import com.topjohnwu.magisk.core.utils.currentLocale
|
||||||
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
||||||
import com.topjohnwu.magisk.events.SnackbarEvent
|
import com.topjohnwu.magisk.events.SnackbarEvent
|
||||||
import com.topjohnwu.magisk.events.dialog.BiometricDialog
|
import com.topjohnwu.magisk.events.dialog.BiometricEvent
|
||||||
import com.topjohnwu.magisk.events.dialog.SuperuserRevokeDialog
|
import com.topjohnwu.magisk.events.dialog.SuperuserRevokeDialog
|
||||||
import com.topjohnwu.magisk.view.TappableHeadlineItem
|
import com.topjohnwu.magisk.view.TappableHeadlineItem
|
||||||
import com.topjohnwu.magisk.view.TextItem
|
import com.topjohnwu.magisk.view.TextItem
|
||||||
@ -86,7 +86,7 @@ class SuperuserViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (BiometricHelper.isEnabled) {
|
if (BiometricHelper.isEnabled) {
|
||||||
BiometricDialog {
|
BiometricEvent {
|
||||||
onSuccess { updateState() }
|
onSuccess { updateState() }
|
||||||
}.publish()
|
}.publish()
|
||||||
} else {
|
} else {
|
||||||
@ -130,7 +130,7 @@ class SuperuserViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (BiometricHelper.isEnabled) {
|
if (BiometricHelper.isEnabled) {
|
||||||
BiometricDialog {
|
BiometricEvent {
|
||||||
onSuccess { updateState() }
|
onSuccess { updateState() }
|
||||||
}.publish()
|
}.publish()
|
||||||
} else {
|
} else {
|
||||||
|
@ -29,7 +29,7 @@ open class SuRequestActivity : BaseUIActivity<SuRequestViewModel, ActivityReques
|
|||||||
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
|
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
lockOrientation()
|
lockOrientation()
|
||||||
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE,
|
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE,
|
||||||
WindowManager.LayoutParams.FLAG_SECURE)
|
WindowManager.LayoutParams.FLAG_SECURE)
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
fun showRequest() {
|
fun showRequest() {
|
||||||
|
@ -13,12 +13,14 @@ import com.topjohnwu.magisk.R
|
|||||||
import com.topjohnwu.magisk.arch.BaseViewModel
|
import com.topjohnwu.magisk.arch.BaseViewModel
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.magiskdb.PolicyDao
|
import com.topjohnwu.magisk.core.magiskdb.PolicyDao
|
||||||
|
import com.topjohnwu.magisk.core.model.su.SuPolicy
|
||||||
import com.topjohnwu.magisk.core.model.su.SuPolicy.Companion.ALLOW
|
import com.topjohnwu.magisk.core.model.su.SuPolicy.Companion.ALLOW
|
||||||
import com.topjohnwu.magisk.core.model.su.SuPolicy.Companion.DENY
|
import com.topjohnwu.magisk.core.model.su.SuPolicy.Companion.DENY
|
||||||
import com.topjohnwu.magisk.core.su.SuRequestHandler
|
import com.topjohnwu.magisk.core.su.SuRequestHandler
|
||||||
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
||||||
import com.topjohnwu.magisk.events.DieEvent
|
import com.topjohnwu.magisk.events.DieEvent
|
||||||
import com.topjohnwu.magisk.events.ShowUIEvent
|
import com.topjohnwu.magisk.events.ShowUIEvent
|
||||||
|
import com.topjohnwu.magisk.events.dialog.BiometricEvent
|
||||||
import com.topjohnwu.magisk.ui.superuser.SpinnerRvItem
|
import com.topjohnwu.magisk.ui.superuser.SpinnerRvItem
|
||||||
import com.topjohnwu.magisk.utils.set
|
import com.topjohnwu.magisk.utils.set
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -28,7 +30,7 @@ import java.util.concurrent.TimeUnit.SECONDS
|
|||||||
|
|
||||||
class SuRequestViewModel(
|
class SuRequestViewModel(
|
||||||
private val pm: PackageManager,
|
private val pm: PackageManager,
|
||||||
private val policyDB: PolicyDao,
|
policyDB: PolicyDao,
|
||||||
private val timeoutPrefs: SharedPreferences,
|
private val timeoutPrefs: SharedPreferences,
|
||||||
private val res: Resources
|
private val res: Resources
|
||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
@ -57,89 +59,86 @@ class SuRequestViewModel(
|
|||||||
setItems(items)
|
setItems(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val handler = Handler()
|
private val handler = SuRequestHandler(pm, policyDB)
|
||||||
|
private lateinit var timer: CountDownTimer
|
||||||
|
|
||||||
fun grantPressed() {
|
fun grantPressed() {
|
||||||
handler.cancelTimer()
|
cancelTimer()
|
||||||
if (BiometricHelper.isEnabled) {
|
if (BiometricHelper.isEnabled) {
|
||||||
withView {
|
BiometricEvent {
|
||||||
BiometricHelper.authenticate(this) {
|
onSuccess {
|
||||||
handler.respond(ALLOW)
|
respond(ALLOW)
|
||||||
}
|
}
|
||||||
}
|
}.publish()
|
||||||
} else {
|
} else {
|
||||||
handler.respond(ALLOW)
|
respond(ALLOW)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun denyPressed() {
|
fun denyPressed() {
|
||||||
handler.respond(DENY)
|
respond(DENY)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun spinnerTouched(): Boolean {
|
fun spinnerTouched(): Boolean {
|
||||||
handler.cancelTimer()
|
cancelTimer()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleRequest(intent: Intent) {
|
fun handleRequest(intent: Intent) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
if (!handler.start(intent))
|
if (handler.start(intent))
|
||||||
|
showDialog(handler.policy)
|
||||||
|
else
|
||||||
DieEvent().publish()
|
DieEvent().publish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class Handler : SuRequestHandler(pm, policyDB) {
|
private fun showDialog(policy: SuPolicy) {
|
||||||
|
icon = policy.applicationInfo.loadIcon(pm)
|
||||||
|
title = policy.appName
|
||||||
|
packageName = policy.packageName
|
||||||
|
selectedItemPosition = timeoutPrefs.getInt(policy.packageName, 0)
|
||||||
|
|
||||||
private lateinit var timer: CountDownTimer
|
// Set timer
|
||||||
|
val millis = SECONDS.toMillis(Config.suDefaultTimeout.toLong())
|
||||||
|
timer = SuTimer(millis, 1000).apply { start() }
|
||||||
|
|
||||||
fun respond(action: Int) {
|
// Actually show the UI
|
||||||
timer.cancel()
|
ShowUIEvent().publish()
|
||||||
|
|
||||||
val pos = selectedItemPosition
|
|
||||||
timeoutPrefs.edit().putInt(policy.packageName, pos).apply()
|
|
||||||
respond(action, Config.Value.TIMEOUT_LIST[pos])
|
|
||||||
|
|
||||||
// Kill activity after response
|
|
||||||
DieEvent().publish()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun cancelTimer() {
|
|
||||||
timer.cancel()
|
|
||||||
denyText = res.getString(R.string.deny)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStart() {
|
|
||||||
icon = policy.applicationInfo.loadIcon(pm)
|
|
||||||
title = policy.appName
|
|
||||||
packageName = policy.packageName
|
|
||||||
selectedItemPosition = timeoutPrefs.getInt(policy.packageName, 0)
|
|
||||||
|
|
||||||
// Set timer
|
|
||||||
val millis = SECONDS.toMillis(Config.suDefaultTimeout.toLong())
|
|
||||||
timer = SuTimer(millis, 1000).apply { start() }
|
|
||||||
|
|
||||||
// Actually show the UI
|
|
||||||
ShowUIEvent().publish()
|
|
||||||
}
|
|
||||||
|
|
||||||
private inner class SuTimer(
|
|
||||||
private val millis: Long,
|
|
||||||
interval: Long
|
|
||||||
) : CountDownTimer(millis, interval) {
|
|
||||||
|
|
||||||
override fun onTick(remains: Long) {
|
|
||||||
if (!grantEnabled && remains <= millis - 1000) {
|
|
||||||
grantEnabled = true
|
|
||||||
}
|
|
||||||
denyText = "${res.getString(R.string.deny)} (${(remains / 1000) + 1})"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFinish() {
|
|
||||||
denyText = res.getString(R.string.deny)
|
|
||||||
respond(DENY)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun respond(action: Int) {
|
||||||
|
timer.cancel()
|
||||||
|
|
||||||
|
val pos = selectedItemPosition
|
||||||
|
timeoutPrefs.edit().putInt(handler.policy.packageName, pos).apply()
|
||||||
|
handler.respond(action, Config.Value.TIMEOUT_LIST[pos])
|
||||||
|
|
||||||
|
// Kill activity after response
|
||||||
|
DieEvent().publish()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cancelTimer() {
|
||||||
|
timer.cancel()
|
||||||
|
denyText = res.getString(R.string.deny)
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class SuTimer(
|
||||||
|
private val millis: Long,
|
||||||
|
interval: Long
|
||||||
|
) : CountDownTimer(millis, interval) {
|
||||||
|
|
||||||
|
override fun onTick(remains: Long) {
|
||||||
|
if (!grantEnabled && remains <= millis - 1000) {
|
||||||
|
grantEnabled = true
|
||||||
|
}
|
||||||
|
denyText = "${res.getString(R.string.deny)} (${(remains / 1000) + 1})"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFinish() {
|
||||||
|
denyText = res.getString(R.string.deny)
|
||||||
|
respond(DENY)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user