Added safetynet implementation

This commit is contained in:
Viktor De Pasquale
2019-10-24 17:33:42 +02:00
parent 21f2f86cb8
commit 9e3afcfe7a
6 changed files with 342 additions and 45 deletions

View File

@@ -1,9 +1,19 @@
package com.topjohnwu.magisk.redesign.safetynet
import android.os.Build
import android.view.View
import android.view.ViewAnimationUtils
import androidx.core.animation.doOnEnd
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.databinding.BindingAdapter
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.FragmentSafetynetMd2Binding
import com.topjohnwu.magisk.redesign.compat.CompatFragment
import org.koin.androidx.viewmodel.ext.android.viewModel
import kotlin.math.hypot
import kotlin.math.roundToInt
class SafetynetFragment : CompatFragment<SafetynetViewModel, FragmentSafetynetMd2Binding>() {
@@ -15,4 +25,34 @@ class SafetynetFragment : CompatFragment<SafetynetViewModel, FragmentSafetynetMd
activity.setTitle(R.string.safetyNet)
}
}
@BindingAdapter("revealSafetyNet")
fun View.revealOnCenter(expand: Boolean) {
val anim = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
isInvisible = expand
return
} else {
val x = measuredWidth.toDouble()
val y = measuredHeight.toDouble()
val maxRadius = hypot(x, y).toFloat()
val start = if (expand) 0f else maxRadius
val end = if (expand) maxRadius else 0f
ViewAnimationUtils.createCircularReveal(
this,
(x / 2).roundToInt(),
(y / 2).roundToInt(),
start,
end
).apply {
interpolator = FastOutSlowInInterpolator()
doOnEnd { if (!expand) isVisible = false }
}
}
post {
isVisible = true
anim.start()
}
}

View File

@@ -1,5 +1,7 @@
package com.topjohnwu.magisk.redesign.safetynet
import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.extensions.subscribeK
import com.topjohnwu.magisk.model.events.SafetyNetResult
@@ -14,44 +16,63 @@ class SafetynetViewModel(
rxBus: RxBus
) : CompatViewModel() {
private var currentState = IDLE
set(value) {
field = value
notifyStateChanged()
}
val safetyNetTitle = KObservableField(R.string.empty)
val ctsState = KObservableField(IDLE)
val basicIntegrityState = KObservableField(IDLE)
val ctsState = KObservableField(false)
val basicIntegrityState = KObservableField(false)
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.responseCode) }
.add()
attest()
}
fun attest() = UpdateSafetyNetEvent().publish()
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: Int) = when {
//todo animate (reveal) to result (green/error)
response and 0x0F == 0 -> {
val hasCtsPassed = response and SafetyNetHelper.CTS_PASS != 0
val hasBasicIntegrityPassed = response and SafetyNetHelper.BASIC_PASS != 0
safetyNetTitle.value = R.string.safetyNet_check_success
ctsState.value = if (hasCtsPassed) {
PASS
} else {
FAILED
}
basicIntegrityState.value = if (hasBasicIntegrityPassed) {
PASS
} else {
FAILED
}
val result = hasCtsPassed && hasBasicIntegrityPassed
ctsState.value = hasCtsPassed
basicIntegrityState.value = hasBasicIntegrityPassed
currentState = if (result) PASS else FAILED
safetyNetTitle.value =
if (result) R.string.safetynet_attest_success
else R.string.safetynet_attest_failure
}
//todo animate (collapse) back to initial (fade error)
response == -2 -> {
ctsState.value = IDLE
basicIntegrityState.value = IDLE
currentState = FAILED
ctsState.value = false
basicIntegrityState.value = false
back()
}
//todo animate (collapse) back to initial (surface)
else -> {
ctsState.value = IDLE
basicIntegrityState.value = IDLE
currentState = FAILED
ctsState.value = false
basicIntegrityState.value = false
safetyNetTitle.value = when (response) {
SafetyNetHelper.RESPONSE_ERR -> R.string.safetyNet_res_invalid
else -> R.string.safetyNet_api_error