Magisk/app/src/main/java/com/topjohnwu/magisk/ui/safetynet/SafetynetViewModel.kt
2020-07-12 03:17:50 -07:00

97 lines
2.8 KiB
Kotlin

package com.topjohnwu.magisk.ui.safetynet
import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.model.events.CheckSafetyNetEvent
import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.ui.safetynet.SafetyNetState.*
import com.topjohnwu.magisk.utils.observable
import org.json.JSONObject
enum class SafetyNetState {
LOADING, PASS, FAILED, IDLE
}
data class SafetyNetResult(
val response: JSONObject? = null,
val dismiss: Boolean = false
)
class SafetynetViewModel : BaseViewModel() {
@get:Bindable
var safetyNetTitle by observable(R.string.empty, BR.safetyNetTitle)
@get:Bindable
var ctsState by observable(false, BR.ctsState)
@get:Bindable
var basicIntegrityState by observable(false, BR.basicIntegrityState)
@get:Bindable
var evalType by observable("")
@get:Bindable
val isChecking get() = currentState == LOADING
@get:Bindable
val isFailed get() = currentState == FAILED
@get:Bindable
val isSuccess get() = currentState == PASS
private var currentState by observable(IDLE, BR.checking, BR.failed, BR.success)
init {
cachedResult?.also {
resolveResponse(SafetyNetResult(it))
} ?: attest()
}
private fun attest() {
currentState = LOADING
CheckSafetyNetEvent() {
resolveResponse(it)
}.publish()
}
fun reset() = attest()
private fun resolveResponse(response: SafetyNetResult) {
if (response.dismiss) {
back()
return
}
response.response?.apply {
runCatching {
val cts = getBoolean("ctsProfileMatch")
val basic = getBoolean("basicIntegrity")
val eval = optString("evaluationType")
val result = cts && basic
cachedResult = this
ctsState = cts
basicIntegrityState = basic
evalType = if (eval.contains("HARDWARE")) "HARDWARE" else "BASIC"
currentState = if (result) PASS else FAILED
safetyNetTitle =
if (result) R.string.safetynet_attest_success
else R.string.safetynet_attest_failure
}.onFailure {
currentState = FAILED
ctsState = false
basicIntegrityState = false
evalType = "N/A"
safetyNetTitle = R.string.safetynet_res_invalid
}
} ?: {
currentState = FAILED
ctsState = false
basicIntegrityState = false
evalType = "N/A"
safetyNetTitle = R.string.safetynet_api_error
}()
}
companion object {
private var cachedResult: JSONObject? = null
}
}