mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-06-13 06:38:39 +00:00
Update UI for sharedUID support
This commit is contained in:
parent
9f1740cc4f
commit
31f88e0f05
@ -2,9 +2,7 @@ package com.topjohnwu.magisk.core.magiskdb
|
|||||||
|
|
||||||
import com.topjohnwu.magisk.core.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.core.model.su.SuPolicy
|
import com.topjohnwu.magisk.core.model.su.SuPolicy
|
||||||
import com.topjohnwu.magisk.core.model.su.createPolicy
|
|
||||||
import com.topjohnwu.magisk.di.AppContext
|
import com.topjohnwu.magisk.di.AppContext
|
||||||
import timber.log.Timber
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class PolicyDao : MagiskDB() {
|
class PolicyDao : MagiskDB() {
|
||||||
@ -23,28 +21,31 @@ class PolicyDao : MagiskDB() {
|
|||||||
|
|
||||||
suspend fun fetch(uid: Int): SuPolicy? {
|
suspend fun fetch(uid: Int): SuPolicy? {
|
||||||
val query = "SELECT * FROM ${Table.POLICY} WHERE uid == $uid LIMIT = 1"
|
val query = "SELECT * FROM ${Table.POLICY} WHERE uid == $uid LIMIT = 1"
|
||||||
return exec(query) { it.toPolicyOrNull() }.firstOrNull()
|
return exec(query, ::toPolicy).firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun update(policy: SuPolicy) {
|
suspend fun update(policy: SuPolicy) {
|
||||||
val query = "REPLACE INTO ${Table.POLICY} ${policy.toMap().toQuery()}"
|
val map = policy.toMap()
|
||||||
|
// Put in package_name for old database
|
||||||
|
map["package_name"] = AppContext.packageManager.getNameForUid(policy.uid)!!
|
||||||
|
val query = "REPLACE INTO ${Table.POLICY} ${map.toQuery()}"
|
||||||
exec(query)
|
exec(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchAll(): List<SuPolicy> {
|
suspend fun fetchAll(): List<SuPolicy> {
|
||||||
val query = "SELECT * FROM ${Table.POLICY} WHERE uid/100000 == ${Const.USER_ID}"
|
val query = "SELECT * FROM ${Table.POLICY} WHERE uid/100000 == ${Const.USER_ID}"
|
||||||
return exec(query) { it.toPolicyOrNull() }.filterNotNull()
|
return exec(query, ::toPolicy).filterNotNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun Map<String, String>.toPolicyOrNull(): SuPolicy? {
|
private fun toPolicy(map: Map<String, String>): SuPolicy? {
|
||||||
try {
|
val uid = map["uid"]?.toInt() ?: return null
|
||||||
return AppContext.packageManager.createPolicy(this)
|
val policy = SuPolicy(uid)
|
||||||
} catch (e: Exception) {
|
|
||||||
Timber.w(e)
|
map["policy"]?.toInt()?.let { policy.policy = it }
|
||||||
val uid = get("uid") ?: return null
|
map["until"]?.toLong()?.let { policy.until = it }
|
||||||
delete(uid.toInt())
|
map["logging"]?.toInt()?.let { policy.logging = it != 0 }
|
||||||
return null
|
map["notification"]?.toInt()?.let { policy.notification = it != 0 }
|
||||||
}
|
return policy
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,75 +1,22 @@
|
|||||||
package com.topjohnwu.magisk.core.model.su
|
package com.topjohnwu.magisk.core.model.su
|
||||||
|
|
||||||
import android.content.pm.PackageInfo
|
class SuPolicy(val uid: Int) {
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import com.topjohnwu.magisk.ktx.getLabel
|
|
||||||
import com.topjohnwu.magisk.ktx.getPackageInfo
|
|
||||||
|
|
||||||
class SuPolicy(
|
|
||||||
val uid: Int,
|
|
||||||
val packageName: String,
|
|
||||||
val appName: String,
|
|
||||||
val icon: Drawable,
|
|
||||||
var policy: Int = INTERACTIVE,
|
|
||||||
var until: Long = -1L,
|
|
||||||
var logging: Boolean = true,
|
|
||||||
var notification: Boolean = true
|
|
||||||
) {
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val INTERACTIVE = 0
|
const val INTERACTIVE = 0
|
||||||
const val DENY = 1
|
const val DENY = 1
|
||||||
const val ALLOW = 2
|
const val ALLOW = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toMap() = mapOf(
|
var policy: Int = INTERACTIVE
|
||||||
|
var until: Long = -1L
|
||||||
|
var logging: Boolean = true
|
||||||
|
var notification: Boolean = true
|
||||||
|
|
||||||
|
fun toMap(): MutableMap<String, Any> = mutableMapOf(
|
||||||
"uid" to uid,
|
"uid" to uid,
|
||||||
"package_name" to packageName,
|
|
||||||
"policy" to policy,
|
"policy" to policy,
|
||||||
"until" to until,
|
"until" to until,
|
||||||
"logging" to logging,
|
"logging" to logging,
|
||||||
"notification" to notification
|
"notification" to notification
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun PackageManager.createPolicy(info: PackageInfo): SuPolicy {
|
|
||||||
val appInfo = info.applicationInfo
|
|
||||||
val prefix = if (info.sharedUserId == null) "" else "[SharedUID] "
|
|
||||||
return SuPolicy(
|
|
||||||
uid = appInfo.uid,
|
|
||||||
packageName = getNameForUid(appInfo.uid)!!,
|
|
||||||
appName = "$prefix${appInfo.getLabel(this)}",
|
|
||||||
icon = appInfo.loadIcon(this),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(PackageManager.NameNotFoundException::class)
|
|
||||||
fun PackageManager.createPolicy(uid: Int): SuPolicy {
|
|
||||||
val info = getPackageInfo(uid, -1)
|
|
||||||
return if (info == null) {
|
|
||||||
// We can assert getNameForUid does not return null because
|
|
||||||
// getPackageInfo will already throw if UID does not exist
|
|
||||||
val name = getNameForUid(uid)!!
|
|
||||||
SuPolicy(
|
|
||||||
uid = uid,
|
|
||||||
packageName = name,
|
|
||||||
appName = "[SharedUID] $name",
|
|
||||||
icon = defaultActivityIcon,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
createPolicy(info)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(PackageManager.NameNotFoundException::class)
|
|
||||||
fun PackageManager.createPolicy(map: Map<String, String>): SuPolicy {
|
|
||||||
val uid = map["uid"]?.toIntOrNull() ?: throw IllegalArgumentException()
|
|
||||||
val policy = createPolicy(uid)
|
|
||||||
|
|
||||||
map["policy"]?.toInt()?.let { policy.policy = it }
|
|
||||||
map["until"]?.toLong()?.let { policy.until = it }
|
|
||||||
map["logging"]?.toInt()?.let { policy.logging = it != 0 }
|
|
||||||
map["notification"]?.toInt()?.let { policy.notification = it != 0 }
|
|
||||||
return policy
|
|
||||||
}
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package com.topjohnwu.magisk.core.su
|
package com.topjohnwu.magisk.core.su
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageInfo
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
import com.topjohnwu.magisk.BuildConfig
|
||||||
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
|
||||||
import com.topjohnwu.magisk.core.model.su.createPolicy
|
|
||||||
import com.topjohnwu.magisk.ktx.getPackageInfo
|
import com.topjohnwu.magisk.ktx.getPackageInfo
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -19,13 +19,15 @@ import java.io.IOException
|
|||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class SuRequestHandler(
|
class SuRequestHandler(
|
||||||
private val pm: PackageManager,
|
val pm: PackageManager,
|
||||||
private val policyDB: PolicyDao
|
private val policyDB: PolicyDao
|
||||||
) : Closeable {
|
) : Closeable {
|
||||||
|
|
||||||
private lateinit var output: DataOutputStream
|
private lateinit var output: DataOutputStream
|
||||||
lateinit var policy: SuPolicy
|
lateinit var policy: SuPolicy
|
||||||
private set
|
private set
|
||||||
|
lateinit var pkgInfo: PackageInfo
|
||||||
|
private set
|
||||||
|
|
||||||
// Return true to indicate undetermined policy, require user interaction
|
// Return true to indicate undetermined policy, require user interaction
|
||||||
suspend fun start(intent: Intent): Boolean {
|
suspend fun start(intent: Intent): Boolean {
|
||||||
@ -33,7 +35,7 @@ class SuRequestHandler(
|
|||||||
return false
|
return false
|
||||||
|
|
||||||
// Never allow com.topjohnwu.magisk (could be malware)
|
// Never allow com.topjohnwu.magisk (could be malware)
|
||||||
if (policy.packageName == BuildConfig.APPLICATION_ID) {
|
if (pkgInfo.packageName == BuildConfig.APPLICATION_ID) {
|
||||||
Shell.cmd("(pm uninstall ${BuildConfig.APPLICATION_ID})& >/dev/null 2>&1").exec()
|
Shell.cmd("(pm uninstall ${BuildConfig.APPLICATION_ID})& >/dev/null 2>&1").exec()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -64,9 +66,9 @@ class SuRequestHandler(
|
|||||||
val fifo = intent.getStringExtra("fifo") ?: throw SuRequestError()
|
val fifo = intent.getStringExtra("fifo") ?: throw SuRequestError()
|
||||||
val uid = intent.getIntExtra("uid", -1).also { if (it < 0) throw SuRequestError() }
|
val uid = intent.getIntExtra("uid", -1).also { if (it < 0) throw SuRequestError() }
|
||||||
val pid = intent.getIntExtra("pid", -1)
|
val pid = intent.getIntExtra("pid", -1)
|
||||||
val info = pm.getPackageInfo(uid, pid) ?: throw SuRequestError()
|
pkgInfo = pm.getPackageInfo(uid, pid) ?: throw SuRequestError()
|
||||||
output = DataOutputStream(FileOutputStream(fifo).buffered())
|
output = DataOutputStream(FileOutputStream(fifo).buffered())
|
||||||
policy = pm.createPolicy(info)
|
policy = SuPolicy(uid)
|
||||||
true
|
true
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
when (e) {
|
when (e) {
|
||||||
|
@ -10,37 +10,49 @@ import com.topjohnwu.magisk.databinding.RvContainer
|
|||||||
import com.topjohnwu.magisk.databinding.set
|
import com.topjohnwu.magisk.databinding.set
|
||||||
|
|
||||||
class PolicyRvItem(
|
class PolicyRvItem(
|
||||||
|
private val viewModel: SuperuserViewModel,
|
||||||
override val item: SuPolicy,
|
override val item: SuPolicy,
|
||||||
|
val packageName: String,
|
||||||
|
private val isSharedUid: Boolean,
|
||||||
val icon: Drawable,
|
val icon: Drawable,
|
||||||
val viewModel: SuperuserViewModel
|
val appName: String
|
||||||
) : ObservableDiffRvItem<PolicyRvItem>(), RvContainer<SuPolicy> {
|
) : ObservableDiffRvItem<PolicyRvItem>(), RvContainer<SuPolicy> {
|
||||||
|
|
||||||
override val layoutRes = R.layout.item_policy_md2
|
override val layoutRes = R.layout.item_policy_md2
|
||||||
|
|
||||||
|
val title get() = if (isSharedUid) "[SharedUID] $appName" else appName
|
||||||
|
|
||||||
|
private inline fun <reified T> setImpl(new: T, old: T, setter: (T) -> Unit) {
|
||||||
|
if (old != new) {
|
||||||
|
setter(new)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var isExpanded = false
|
var isExpanded = false
|
||||||
set(value) = set(value, field, { field = it }, BR.expanded)
|
set(value) = set(value, field, { field = it }, BR.expanded)
|
||||||
|
|
||||||
// This property binds with the UI state
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var isEnabled
|
var isEnabled
|
||||||
get() = item.policy == SuPolicy.ALLOW
|
get() = item.policy == SuPolicy.ALLOW
|
||||||
set(value) {
|
set(value) = setImpl(value, isEnabled) {
|
||||||
if (value != isEnabled)
|
viewModel.togglePolicy(this, value)
|
||||||
viewModel.togglePolicy(this, value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var shouldNotify
|
var shouldNotify
|
||||||
get() = item.notification
|
get() = item.notification
|
||||||
set(value) = set(value, shouldNotify, { item.notification = it }, BR.shouldNotify) {
|
private set(value) = setImpl(value, shouldNotify) {
|
||||||
viewModel.updatePolicy(item, isLogging = false)
|
item.notification = it
|
||||||
|
viewModel.updateNotify(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var shouldLog
|
var shouldLog
|
||||||
get() = item.logging
|
get() = item.logging
|
||||||
set(value) = set(value, shouldLog, { item.logging = it }, BR.shouldLog) {
|
private set(value) = setImpl(value, shouldLog) {
|
||||||
viewModel.updatePolicy(item, isLogging = true)
|
item.logging = it
|
||||||
|
viewModel.updateLogging(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleExpand() {
|
fun toggleExpand() {
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package com.topjohnwu.magisk.ui.superuser
|
package com.topjohnwu.magisk.ui.superuser
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES
|
||||||
import androidx.databinding.ObservableArrayList
|
import androidx.databinding.ObservableArrayList
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
@ -12,9 +15,11 @@ import com.topjohnwu.magisk.core.utils.currentLocale
|
|||||||
import com.topjohnwu.magisk.databinding.AnyDiffRvItem
|
import com.topjohnwu.magisk.databinding.AnyDiffRvItem
|
||||||
import com.topjohnwu.magisk.databinding.diffListOf
|
import com.topjohnwu.magisk.databinding.diffListOf
|
||||||
import com.topjohnwu.magisk.databinding.itemBindingOf
|
import com.topjohnwu.magisk.databinding.itemBindingOf
|
||||||
|
import com.topjohnwu.magisk.di.AppContext
|
||||||
import com.topjohnwu.magisk.events.SnackbarEvent
|
import com.topjohnwu.magisk.events.SnackbarEvent
|
||||||
import com.topjohnwu.magisk.events.dialog.BiometricEvent
|
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.ktx.getLabel
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
import com.topjohnwu.magisk.utils.Utils
|
||||||
import com.topjohnwu.magisk.utils.asText
|
import com.topjohnwu.magisk.utils.asText
|
||||||
import com.topjohnwu.magisk.view.TextItem
|
import com.topjohnwu.magisk.view.TextItem
|
||||||
@ -41,6 +46,7 @@ class SuperuserViewModel(
|
|||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
|
@SuppressLint("InlinedApi")
|
||||||
override fun refresh() = viewModelScope.launch {
|
override fun refresh() = viewModelScope.launch {
|
||||||
if (!Utils.showSuperUser()) {
|
if (!Utils.showSuperUser()) {
|
||||||
state = State.LOADING_FAILED
|
state = State.LOADING_FAILED
|
||||||
@ -49,11 +55,28 @@ class SuperuserViewModel(
|
|||||||
state = State.LOADING
|
state = State.LOADING
|
||||||
val (policies, diff) = withContext(Dispatchers.IO) {
|
val (policies, diff) = withContext(Dispatchers.IO) {
|
||||||
db.deleteOutdated()
|
db.deleteOutdated()
|
||||||
val policies = db.fetchAll().map {
|
val policies = ArrayList<PolicyRvItem>()
|
||||||
PolicyRvItem(it, it.icon, this@SuperuserViewModel)
|
val pm = AppContext.packageManager
|
||||||
}.sortedWith(compareBy(
|
for (policy in db.fetchAll()) {
|
||||||
{ it.item.appName.lowercase(currentLocale) },
|
val pkgs = pm.getPackagesForUid(policy.uid) ?: continue
|
||||||
{ it.item.packageName }
|
policies.addAll(pkgs.mapNotNull { pkg ->
|
||||||
|
try {
|
||||||
|
val info = pm.getPackageInfo(pkg, MATCH_UNINSTALLED_PACKAGES)
|
||||||
|
PolicyRvItem(
|
||||||
|
this@SuperuserViewModel, policy,
|
||||||
|
info.packageName,
|
||||||
|
info.sharedUserId != null,
|
||||||
|
info.applicationInfo.loadIcon(pm),
|
||||||
|
info.applicationInfo.getLabel(pm)
|
||||||
|
)
|
||||||
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
policies.sortWith(compareBy(
|
||||||
|
{ it.appName.lowercase(currentLocale) },
|
||||||
|
{ it.packageName }
|
||||||
))
|
))
|
||||||
policies to itemsPolicies.calculateDiff(policies)
|
policies to itemsPolicies.calculateDiff(policies)
|
||||||
}
|
}
|
||||||
@ -82,40 +105,56 @@ class SuperuserViewModel(
|
|||||||
}.publish()
|
}.publish()
|
||||||
} else {
|
} else {
|
||||||
SuperuserRevokeDialog {
|
SuperuserRevokeDialog {
|
||||||
appName = item.item.appName
|
appName = item.title
|
||||||
onSuccess { updateState() }
|
onSuccess { updateState() }
|
||||||
}.publish()
|
}.publish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
fun updateNotify(item: PolicyRvItem) {
|
||||||
|
viewModelScope.launch {
|
||||||
fun updatePolicy(policy: SuPolicy, isLogging: Boolean) = viewModelScope.launch {
|
db.update(item.item)
|
||||||
db.update(policy)
|
val res = when {
|
||||||
val res = when {
|
item.item.logging -> R.string.su_snack_log_on
|
||||||
isLogging -> when {
|
|
||||||
policy.logging -> R.string.su_snack_log_on
|
|
||||||
else -> R.string.su_snack_log_off
|
else -> R.string.su_snack_log_off
|
||||||
}
|
}
|
||||||
else -> when {
|
itemsPolicies.forEach {
|
||||||
policy.notification -> R.string.su_snack_notif_on
|
if (it.item.uid == item.item.uid) {
|
||||||
|
it.notifyPropertyChanged(BR.shouldNotify)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SnackbarEvent(res.asText(item.appName)).publish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateLogging(item: PolicyRvItem) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
db.update(item.item)
|
||||||
|
val res = when {
|
||||||
|
item.item.notification -> R.string.su_snack_notif_on
|
||||||
else -> R.string.su_snack_notif_off
|
else -> R.string.su_snack_notif_off
|
||||||
}
|
}
|
||||||
|
itemsPolicies.forEach {
|
||||||
|
if (it.item.uid == item.item.uid) {
|
||||||
|
it.notifyPropertyChanged(BR.shouldLog)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SnackbarEvent(res.asText(item.appName)).publish()
|
||||||
}
|
}
|
||||||
SnackbarEvent(res.asText(policy.appName)).publish()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun togglePolicy(item: PolicyRvItem, enable: Boolean) {
|
fun togglePolicy(item: PolicyRvItem, enable: Boolean) {
|
||||||
fun updateState() {
|
fun updateState() {
|
||||||
val policy = if (enable) SuPolicy.ALLOW else SuPolicy.DENY
|
|
||||||
item.item.policy = policy
|
|
||||||
item.notifyPropertyChanged(BR.enabled)
|
|
||||||
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
val res = if (enable) R.string.su_snack_grant else R.string.su_snack_deny
|
||||||
|
item.item.policy = if (enable) SuPolicy.ALLOW else SuPolicy.DENY
|
||||||
db.update(item.item)
|
db.update(item.item)
|
||||||
val res = if (item.item.policy == SuPolicy.ALLOW) R.string.su_snack_grant
|
itemsPolicies.forEach {
|
||||||
else R.string.su_snack_deny
|
if (it.item.uid == item.item.uid) {
|
||||||
SnackbarEvent(res.asText(item.item.appName)).publish()
|
it.notifyPropertyChanged(BR.enabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SnackbarEvent(res.asText(item.appName)).publish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ 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
|
||||||
@ -31,6 +30,7 @@ import com.topjohnwu.magisk.di.AppContext
|
|||||||
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.events.dialog.BiometricEvent
|
||||||
|
import com.topjohnwu.magisk.ktx.getLabel
|
||||||
import com.topjohnwu.magisk.utils.TextHolder
|
import com.topjohnwu.magisk.utils.TextHolder
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
import com.topjohnwu.magisk.utils.Utils
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -100,17 +100,21 @@ class SuRequestViewModel(
|
|||||||
fun handleRequest(intent: Intent) {
|
fun handleRequest(intent: Intent) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
if (handler.start(intent))
|
if (handler.start(intent))
|
||||||
showDialog(handler.policy)
|
showDialog()
|
||||||
else
|
else
|
||||||
DieEvent().publish()
|
DieEvent().publish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showDialog(policy: SuPolicy) {
|
private fun showDialog() {
|
||||||
icon = policy.icon
|
val pm = handler.pm
|
||||||
title = policy.appName
|
val info = handler.pkgInfo
|
||||||
packageName = policy.packageName
|
val prefix = if (info.sharedUserId == null) "" else "[SharedUID] "
|
||||||
selectedItemPosition = timeoutPrefs.getInt(policy.packageName, 0)
|
|
||||||
|
icon = info.applicationInfo.loadIcon(pm)
|
||||||
|
title = "$prefix${info.applicationInfo.getLabel(pm)}"
|
||||||
|
packageName = info.packageName
|
||||||
|
selectedItemPosition = timeoutPrefs.getInt(packageName, 0)
|
||||||
|
|
||||||
// Set timer
|
// Set timer
|
||||||
val millis = SECONDS.toMillis(Config.suDefaultTimeout.toLong())
|
val millis = SECONDS.toMillis(Config.suDefaultTimeout.toLong())
|
||||||
@ -124,7 +128,7 @@ class SuRequestViewModel(
|
|||||||
timer?.cancel()
|
timer?.cancel()
|
||||||
|
|
||||||
val pos = selectedItemPosition
|
val pos = selectedItemPosition
|
||||||
timeoutPrefs.edit().putInt(handler.policy.packageName, pos).apply()
|
timeoutPrefs.edit().putInt(handler.pkgInfo.packageName, pos).apply()
|
||||||
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
handler.respond(action, Config.Value.TIMEOUT_LIST[pos])
|
handler.respond(action, Config.Value.TIMEOUT_LIST[pos])
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
android:ellipsize="middle"
|
android:ellipsize="middle"
|
||||||
android:gravity="start"
|
android:gravity="start"
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
android:text="@{item.item.appName}"
|
android:text="@{item.title}"
|
||||||
android:textAppearance="@style/AppearanceFoundation.Body"
|
android:textAppearance="@style/AppearanceFoundation.Body"
|
||||||
android:textIsSelectable="false"
|
android:textIsSelectable="false"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
@ -71,7 +71,7 @@
|
|||||||
android:ellipsize="middle"
|
android:ellipsize="middle"
|
||||||
android:gravity="start"
|
android:gravity="start"
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
android:text="@{item.item.packageName}"
|
android:text="@{item.packageName}"
|
||||||
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
|
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
|
||||||
android:textColor="@android:color/tertiary_text_dark"
|
android:textColor="@android:color/tertiary_text_dark"
|
||||||
android:textIsSelectable="false"
|
android:textIsSelectable="false"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user