mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-04-16 13:41:25 +00:00
136 lines
4.2 KiB
Kotlin
136 lines
4.2 KiB
Kotlin
package com.topjohnwu.magisk.utils
|
|
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.os.Build
|
|
import android.os.Bundle
|
|
import android.os.Process
|
|
import android.widget.Toast
|
|
import com.topjohnwu.magisk.*
|
|
import com.topjohnwu.magisk.data.repository.LogRepository
|
|
import com.topjohnwu.magisk.extensions.get
|
|
import com.topjohnwu.magisk.extensions.startActivity
|
|
import com.topjohnwu.magisk.extensions.startActivityWithRoot
|
|
import com.topjohnwu.magisk.extensions.subscribeK
|
|
import com.topjohnwu.magisk.model.entity.MagiskPolicy
|
|
import com.topjohnwu.magisk.model.entity.toLog
|
|
import com.topjohnwu.magisk.model.entity.toPolicy
|
|
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity
|
|
import com.topjohnwu.superuser.Shell
|
|
import timber.log.Timber
|
|
|
|
object SuHandler : ProviderCallHandler {
|
|
|
|
const val REQUEST = "request"
|
|
const val LOG = "log"
|
|
const val NOTIFY = "notify"
|
|
const val TEST = "test"
|
|
|
|
override fun call(context: Context, method: String, arg: String?, extras: Bundle?): Bundle? {
|
|
invoke(context.wrap(), method, extras)
|
|
return null
|
|
}
|
|
|
|
operator fun invoke(context: Context, action: String?, data: Bundle?) {
|
|
data ?: return
|
|
|
|
// Debug messages
|
|
if (BuildConfig.DEBUG) {
|
|
Timber.d(action)
|
|
data.let { bundle ->
|
|
bundle.keySet().forEach {
|
|
Timber.d("[%s]=[%s]", it, bundle[it])
|
|
}
|
|
}
|
|
}
|
|
|
|
when (action) {
|
|
REQUEST -> {
|
|
val intent = context.intent<SuRequestActivity>()
|
|
.setAction(action)
|
|
.putExtras(data)
|
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
|
|
if (Build.VERSION.SDK_INT >= 29) {
|
|
// Android Q does not allow starting activity from background
|
|
intent.startActivityWithRoot()
|
|
} else {
|
|
intent.startActivity(context)
|
|
}
|
|
}
|
|
LOG -> handleLogs(context, data)
|
|
NOTIFY -> handleNotify(context, data)
|
|
TEST -> {
|
|
val mode = data.getInt("mode", 2)
|
|
Shell.su(
|
|
"magisk --connect-mode $mode",
|
|
"magisk --use-broadcast"
|
|
).submit()
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun Any?.toInt(): Int? {
|
|
return when (this) {
|
|
is Int -> this
|
|
is Long -> this.toInt()
|
|
else -> null
|
|
}
|
|
}
|
|
|
|
private fun handleLogs(context: Context, data: Bundle) {
|
|
val fromUid = data["from.uid"].toInt() ?: return
|
|
if (fromUid == Process.myUid())
|
|
return
|
|
|
|
val pm = context.packageManager
|
|
|
|
val notify = data.getBoolean("notify", true)
|
|
val allow = data["policy"].toInt() ?: return
|
|
|
|
val policy = runCatching { fromUid.toPolicy(pm, allow) }.getOrElse { return }
|
|
|
|
if (notify)
|
|
notify(context, policy)
|
|
|
|
val toUid = data["to.uid"].toInt() ?: return
|
|
val pid = data["pid"].toInt() ?: return
|
|
|
|
val command = data.getString("command") ?: return
|
|
val log = policy.toLog(
|
|
toUid = toUid,
|
|
fromPid = pid,
|
|
command = command
|
|
)
|
|
|
|
val logRepo = get<LogRepository>()
|
|
logRepo.insert(log).subscribeK(onError = { Timber.e(it) })
|
|
}
|
|
|
|
private fun handleNotify(context: Context, data: Bundle) {
|
|
val fromUid = data["from.uid"].toInt() ?: return
|
|
if (fromUid == Process.myUid())
|
|
return
|
|
|
|
val pm = context.packageManager
|
|
val allow = data["policy"].toInt() ?: return
|
|
|
|
runCatching {
|
|
val policy = fromUid.toPolicy(pm, allow)
|
|
if (policy.policy >= 0)
|
|
notify(context, policy)
|
|
}
|
|
}
|
|
|
|
private fun notify(context: Context, policy: MagiskPolicy) {
|
|
if (policy.notification && Config.suNotification == Config.Value.NOTIFICATION_TOAST) {
|
|
val resId = if (policy.policy == MagiskPolicy.ALLOW)
|
|
R.string.su_allow_toast
|
|
else
|
|
R.string.su_deny_toast
|
|
|
|
Utils.toast(context.getString(resId, policy.appName), Toast.LENGTH_SHORT)
|
|
}
|
|
}
|
|
}
|