Compare commits

...

2 commits

Author SHA1 Message Date
d7214141e6 ui: wizard: Only show full APDU response when it is a failure
All checks were successful
/ build-debug (push) Successful in 5m12s
2024-11-24 19:45:05 -05:00
326b39ed05 ui: wizard: Add APDU errors to diagnostics 2024-11-24 19:43:42 -05:00
4 changed files with 62 additions and 2 deletions

View file

@ -81,6 +81,35 @@ class DownloadWizardDiagnosticsFragment : DownloadWizardActivity.DownloadWizardS
ret.appendLine()
}
err.lastApduResponse?.let { resp ->
val isSuccess =
resp.size >= 2 && resp[resp.size - 2] == 0x90.toByte() && resp[resp.size - 1] == 0x00.toByte()
if (isSuccess) {
ret.appendLine(getString(R.string.download_wizard_diagnostics_last_apdu_response_success))
} else {
// Only show the full APDU response when it's a failure
// Otherwise it's going to get very crammed
ret.appendLine(
getString(
R.string.download_wizard_diagnostics_last_apdu_response,
resp.encodeHex()
)
)
ret.appendLine()
ret.appendLine(getString(R.string.download_wizard_diagnostics_last_apdu_response_fail))
}
}
err.lastApduException?.let { e ->
ret.appendLine(getString(R.string.download_wizard_diagnostics_last_apdu_exception))
ret.appendLine()
ret.appendLine("${e.javaClass.name}: ${e.message}")
ret.appendLine(e.stackTrace.joinToString("\n"))
ret.appendLine()
}
ret.toString()
}
}

View file

@ -85,6 +85,10 @@
<string name="download_wizard_diagnostics_last_http_status">Last HTTP status: %d</string>
<string name="download_wizard_diagnostics_last_http_response">Last HTTP response:</string>
<string name="download_wizard_diagnostics_last_http_exception">Last HTTP exception:</string>
<string name="download_wizard_diagnostics_last_apdu_response">Last APDU response: %s</string>
<string name="download_wizard_diagnostics_last_apdu_response_success">Last APDU response is successful</string>
<string name="download_wizard_diagnostics_last_apdu_response_fail">Last APDU response is a failure</string>
<string name="download_wizard_diagnostics_last_apdu_exception">Last APDU exception:</string>
<string name="profile_rename_new_name">New nickname</string>

View file

@ -3,9 +3,12 @@ package net.typeblog.lpac_jni
import net.typeblog.lpac_jni.HttpInterface.HttpResponse
interface LocalProfileAssistant {
@Suppress("ArrayInDataClass")
data class ProfileDownloadException(
val lastHttpResponse: HttpResponse?,
val lastHttpException: Exception?,
val lastApduResponse: ByteArray?,
val lastApduException: Exception?,
) : Exception("Failed to download profile")
val valid: Boolean

View file

@ -11,13 +11,35 @@ import net.typeblog.lpac_jni.LocalProfileNotification
import net.typeblog.lpac_jni.ProfileDownloadCallback
class LocalProfileAssistantImpl(
private val apduInterface: ApduInterface,
rawApduInterface: ApduInterface,
private val httpInterface: HttpInterface
): LocalProfileAssistant {
companion object {
private const val TAG = "LocalProfileAssistantImpl"
}
/**
* A thin wrapper over ApduInterface to acquire exceptions and errors transparently
*/
private class ApduInterfaceWrapper(val apduInterface: ApduInterface) :
ApduInterface by apduInterface {
var lastApduResponse: ByteArray? = null
var lastApduException: Exception? = null
override fun transmit(tx: ByteArray): ByteArray =
try {
apduInterface.transmit(tx).also {
lastApduResponse = it
}
} catch (e: Exception) {
lastApduResponse = null
lastApduException = e
throw e
}
}
private val apduInterface = ApduInterfaceWrapper(rawApduInterface)
private var finalized = false
private var contextHandle: Long = LpacJni.createContext(apduInterface, httpInterface)
@ -157,7 +179,9 @@ class LocalProfileAssistantImpl(
if (res != 0) {
throw LocalProfileAssistant.ProfileDownloadException(
httpInterface.lastHttpResponse,
httpInterface.lastHttpException
httpInterface.lastHttpException,
apduInterface.lastApduResponse,
apduInterface.lastApduException,
)
}
}