Skip to content

Commit

Permalink
UI Refresh for Provisioning a Personal ID
Browse files Browse the repository at this point in the history
- Updated MRZ screen to have rounder corners Camera view.
- NFC contactless heartbeat animation for idle, scanning and error.
- Added new icon assets and updated text.
- Updated downstream to upstream text/string sharing.
- Added nfc-successful-scanning and evidence-request-complete screens.

Tested by:
- Manual testing of MRZ and NFC using the back of Test eID-Karte of Erika Mustermann
- ./gradlew connectedCheck
- ./gradlew check

Signed-off-by: dritan-x <[email protected]>
  • Loading branch information
dritan-x committed Nov 4, 2024
1 parent 322b109 commit 0a9bdbc
Show file tree
Hide file tree
Showing 13 changed files with 598 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@ import kotlinx.io.bytestring.ByteString
* [assets] images that can be referenced in markdown, type (PNG, JPEG, or SVG) determined by the extension
* [acceptButtonText] button label to continue to the next screen
* [rejectButtonText] optional button label to continue without accepting
* [messageType] optional identifier used for classifying message types (success, error, info, ..)
* for showing a more appropriate UI than a standard basic message
* [messageTitle] optional title to show above the message for a non-standard or non-basic message
* that is filtered/classified via the [messageType]
*/
data class EvidenceRequestMessage(
val message: String,
val assets: Map<String, ByteString>,
val acceptButtonText: String,
val rejectButtonText: String?,
val messageType: String? = null,
val messageTitle: String? = null
) : EvidenceRequest()
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import com.android.identity.issuance.evidence.EvidenceRequestQuestionString
import com.android.identity.issuance.evidence.EvidenceRequestSelfieVideo
import com.android.identity.issuance.evidence.EvidenceRequestSetupCloudSecureArea
import com.android.identity.issuance.evidence.EvidenceResponse
import com.android.identity.securearea.PassphraseConstraints
import com.android.identity.issuance.proofing.ProofingGraph.Node
import com.android.identity.securearea.PassphraseConstraints
import kotlinx.io.bytestring.ByteString

/**
Expand All @@ -27,9 +27,24 @@ class ProofingGraphBuilder {
private val chain = mutableListOf<(Node?) -> Node>()

/** Sends [EvidenceRequestMessage]. */
fun message(id: String, message: String, assets: Map<String, ByteString>,
acceptButtonText: String, rejectButtonText: String?) {
val evidenceRequest = EvidenceRequestMessage(message, assets, acceptButtonText, rejectButtonText)
fun message(
id: String,
message: String,
assets: Map<String, ByteString>,
acceptButtonText: String,
rejectButtonText: String?,
messageType: String? = null,
messageTitle: String? = null
) {
val evidenceRequest =
EvidenceRequestMessage(
message,
assets,
acceptButtonText,
rejectButtonText,
messageType,
messageTitle,
)
chain.add { followUp -> ProofingGraph.SimpleNode(id, followUp, evidenceRequest) }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,18 @@ fun defaultGraph(
}
}
message(
"message",
message = """
id = "message",
message = resources.getStringResource("R.string.evidence_request_complete_info") ?: """
Your application is about to be sent the ID issuer for verification. You will
get notified when the application is approved.
""".trimIndent(),
messageType = "evidence_request_complete",
messageTitle = resources.getStringResource("R.string.evidence_request_complete_title")
?: "Submitted for Verification",
assets = mapOf(),
acceptButtonText = "Continue",
null
acceptButtonText = resources.getStringResource("R.string.evidence_request_complete_done_button")
?: "Continue",
rejectButtonText = null
)
requestNotificationPermission(
"notificationPermission",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import androidx.activity.ComponentActivity
import androidx.camera.core.CameraSelector
import androidx.camera.core.ExperimentalGetImage
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST
import androidx.camera.core.ImageProxy
import androidx.camera.core.Preview
import androidx.camera.core.resolutionselector.ResolutionSelector
import androidx.camera.core.resolutionselector.ResolutionStrategy
import androidx.camera.lifecycle.ProcessCameraProvider
import com.google.mlkit.vision.common.InputImage
import com.google.mlkit.vision.text.TextRecognition
Expand Down Expand Up @@ -46,10 +49,20 @@ class MrtdMrzScanner(private val mActivity: ComponentActivity) {
val previewUseCase = Preview.Builder().build()
previewUseCase.setSurfaceProvider(surfaceProvider)

val analysisBuilder = ImageAnalysis.Builder()
// we take the portrait format of the Image.
analysisBuilder.setTargetResolution(Size(4 * 480, 4 * 640))
val analysisUseCase = analysisBuilder.build()
val analysisUseCase = ImageAnalysis.Builder()
.setResolutionSelector(
ResolutionSelector.Builder()
.setResolutionStrategy(
ResolutionStrategy(
Size(4 * 480, 4 * 640),
ResolutionStrategy.FALLBACK_RULE_CLOSEST_HIGHER_THEN_LOWER
)
)
.build()
)
.setBackpressureStrategy(STRATEGY_KEEP_ONLY_LATEST)
.build()
val executor = Executors.newFixedThreadPool(1)!!
return suspendCoroutine { continuation ->
analysisUseCase.setAnalyzer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Handler
import androidx.annotation.RawRes
import com.android.identity.flow.handler.FlowNotifications
import com.android.identity.flow.server.Configuration
import com.android.identity.flow.server.FlowEnvironment
import com.android.identity.flow.server.Resources
import com.android.identity.flow.server.Storage
import com.android.identity.flow.server.FlowEnvironment
import com.android.identity.flow.handler.FlowNotifications
import com.android.identity.issuance.ApplicationSupport
import com.android.identity.securearea.SecureArea
import com.android.identity_credential.wallet.R
Expand Down Expand Up @@ -199,7 +199,28 @@ internal class LocalDevelopmentEnvironment(
context.resources.getString(R.string.utopia_local_issuing_authority_photoid_tos)
"funke/tos.html" ->
context.resources.getString(R.string.funke_issuing_authority_tos)
else -> null
else -> {
// String passthrough allowing upstream code to reference downstream Strings
// there's no need to hard-code/define every possible String in here
if (name.startsWith("R.string.")){
val stringName = name.split("R.string.")[1]
/**
* Localized function resolving a String resource ID from a String's name.
* Note: This approach uses reflection under the hood and is less efficient
* than retrieving a String directly by its identifier. If this ends
* up being a bottleneck we can change the approach of how downstream
* Strings/resources are shared upstream.
*/
fun getStringResId(stringName: String): Int {
return context.resources.getIdentifier(stringName, "string", context.packageName)
}
// return the requested String's value
context.resources.getString(getStringResId(stringName))
} else {
// unknown raw file name or String resource, return null
null
}
}
}
}

Expand Down
Loading

0 comments on commit 0a9bdbc

Please sign in to comment.