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

103 lines
3.1 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
2019-10-24 17:33:42 +02:00
import androidx.databinding.Bindable
2020-07-08 15:14:32 +02:00
import androidx.databinding.ObservableField
2019-10-24 17:33:42 +02:00
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.extensions.subscribeK
2020-07-08 15:14:32 +02:00
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.model.events.SafetyNetResult
import com.topjohnwu.magisk.model.events.UpdateSafetyNetEvent
2020-01-13 15:01:46 +01:00
import com.topjohnwu.magisk.ui.base.BaseViewModel
2020-01-12 17:43:09 +01:00
import com.topjohnwu.magisk.ui.safetynet.SafetyNetState.*
import com.topjohnwu.magisk.utils.RxBus
import org.json.JSONObject
2019-10-17 18:57:00 +02:00
2020-01-12 09:07:30 +01:00
enum class SafetyNetState {
LOADING, PASS, FAILED, IDLE
}
class SafetynetViewModel(
rxBus: RxBus
) : BaseViewModel() {
2019-10-24 17:33:42 +02:00
private var currentState = IDLE
set(value) {
field = value
notifyStateChanged()
}
2020-07-08 15:14:32 +02:00
val safetyNetTitle = ObservableField(R.string.empty)
val ctsState = ObservableField(false)
val basicIntegrityState = ObservableField(false)
val evalType = ObservableField("")
2019-10-24 17:33:42 +02:00
val isChecking @Bindable get() = currentState == LOADING
val isFailed @Bindable get() = currentState == FAILED
val isSuccess @Bindable get() = currentState == PASS
init {
rxBus.register<SafetyNetResult>()
.subscribeK { resolveResponse(it) }
.add()
2019-10-24 17:33:42 +02:00
cachedResult?.also {
resolveResponse(SafetyNetResult(it))
} ?: attest()
}
2019-10-24 17:33:42 +02:00
override fun notifyStateChanged() {
super.notifyStateChanged()
notifyPropertyChanged(BR.loading)
notifyPropertyChanged(BR.failed)
notifyPropertyChanged(BR.success)
}
private fun attest() {
currentState = LOADING
UpdateSafetyNetEvent().publish()
}
fun reset() = attest()
private fun resolveResponse(response: SafetyNetResult) {
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
ctsState.value = cts
basicIntegrityState.value = basic
2020-06-30 12:56:41 +02:00
evalType.value = if (eval.contains("HARDWARE")) "HARDWARE" else "BASIC"
currentState = if (result) PASS else FAILED
safetyNetTitle.value =
if (result) R.string.safetynet_attest_success
else R.string.safetynet_attest_failure
}.onFailure {
currentState = FAILED
ctsState.value = false
basicIntegrityState.value = false
2020-06-30 12:56:41 +02:00
evalType.value = "N/A"
safetyNetTitle.value = R.string.safetynet_res_invalid
}
} ?: {
2019-10-24 17:33:42 +02:00
currentState = FAILED
ctsState.value = false
basicIntegrityState.value = false
2020-06-30 12:56:41 +02:00
evalType.value = "N/A"
safetyNetTitle.value = R.string.safetynet_api_error
}()
}
companion object {
private var cachedResult: JSONObject? = null
}
2020-01-12 09:07:30 +01:00
}