Magisk/app/src/main/java/com/topjohnwu/magisk/ui/safetynet/SafetynetViewModel.kt

113 lines
3.2 KiB
Kotlin
Raw Normal View History

2020-01-12 17:43:09 +01:00
package com.topjohnwu.magisk.ui.safetynet
2019-10-17 18:57:00 +02:00
2020-09-13 09:23:23 +02:00
import android.util.TypedValue
import android.view.ContextThemeWrapper
2019-10-24 17:33:42 +02:00
import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
2020-08-18 15:31:15 +02:00
import com.topjohnwu.magisk.arch.BaseViewModel
2020-07-15 10:21:57 +02:00
import com.topjohnwu.magisk.utils.set
import org.json.JSONObject
2019-10-17 18:57:00 +02:00
2020-07-09 14:13:24 +02:00
data class SafetyNetResult(
val response: JSONObject? = null,
val dismiss: Boolean = false
)
2020-09-13 09:23:23 +02:00
class SafetynetViewModel(context: ContextThemeWrapper) : BaseViewModel() {
2020-07-12 12:17:50 +02:00
@get:Bindable
2020-07-15 10:21:57 +02:00
var safetyNetTitle = R.string.empty
set(value) = set(value, field, { field = it }, BR.safetyNetTitle)
2020-07-12 12:17:50 +02:00
@get:Bindable
2020-07-15 10:21:57 +02:00
var ctsState = false
set(value) = set(value, field, { field = it }, BR.ctsState)
2020-07-12 12:17:50 +02:00
@get:Bindable
2020-07-15 10:21:57 +02:00
var basicIntegrityState = false
set(value) = set(value, field, { field = it }, BR.basicIntegrityState)
2020-07-12 12:17:50 +02:00
@get:Bindable
2020-07-15 10:21:57 +02:00
var evalType = ""
set(value) = set(value, field, { field = it }, BR.evalType)
2020-07-12 12:17:50 +02:00
@get:Bindable
2020-09-13 09:23:23 +02:00
var isChecking = false
set(value) = set(value, field, { field = it }, BR.checking)
2020-07-12 12:17:50 +02:00
@get:Bindable
2020-09-13 09:23:23 +02:00
var isSuccess = false
set(value) = set(value, field, { field = it }, BR.success, BR.textColor)
2020-07-12 12:17:50 +02:00
@get:Bindable
2020-09-13 09:23:23 +02:00
val textColor get() = if (isSuccess) colorOnPrimary else colorOnError
2019-10-24 17:33:42 +02:00
2020-09-13 09:23:23 +02:00
private val colorOnPrimary: Int
private val colorOnError: Int
init {
2020-09-13 09:23:23 +02:00
val tv = TypedValue()
context.theme.resolveAttribute(R.attr.colorOnPrimary, tv, true)
colorOnPrimary = tv.data
context.theme.resolveAttribute(R.attr.colorOnError, tv, true)
colorOnError = tv.data
cachedResult?.also {
resolveResponse(SafetyNetResult(it))
} ?: attest()
}
2019-10-24 17:33:42 +02:00
private fun attest() {
2020-09-13 09:23:23 +02:00
isChecking = true
CheckSafetyNetEvent {
2020-07-09 14:13:24 +02:00
resolveResponse(it)
}.publish()
2019-10-24 17:33:42 +02:00
}
fun reset() = attest()
private fun resolveResponse(response: SafetyNetResult) {
2020-09-13 09:23:23 +02:00
isChecking = false
if (response.dismiss) {
2019-10-24 17:33:42 +02:00
back()
return
}
response.response?.apply {
runCatching {
val cts = getBoolean("ctsProfileMatch")
val basic = getBoolean("basicIntegrity")
2020-06-30 12:56:41 +02:00
val eval = optString("evaluationType")
val result = cts && basic
cachedResult = this
2020-07-12 12:17:50 +02:00
ctsState = cts
basicIntegrityState = basic
evalType = if (eval.contains("HARDWARE")) "HARDWARE" else "BASIC"
2020-09-13 09:23:23 +02:00
isSuccess = result
2020-07-12 12:17:50 +02:00
safetyNetTitle =
if (result) R.string.safetynet_attest_success
else R.string.safetynet_attest_failure
}.onFailure {
2020-09-13 09:23:23 +02:00
isSuccess = false
2020-07-12 12:17:50 +02:00
ctsState = false
basicIntegrityState = false
evalType = "N/A"
safetyNetTitle = R.string.safetynet_res_invalid
}
} ?: {
2020-09-13 09:23:23 +02:00
isSuccess = false
2020-07-12 12:17:50 +02:00
ctsState = false
basicIntegrityState = false
evalType = "N/A"
safetyNetTitle = R.string.safetynet_api_error
}()
}
companion object {
private var cachedResult: JSONObject? = null
}
2020-01-12 09:07:30 +01:00
}