.. _ChapterEnablingAdvancedInjectionAttackDetection:
********************************************
Enabling Advanced Injection Attack Detection
********************************************
Overview
--------
Face Capture has introduced a new workflow option for advanced injection attack detection, ``LIGHT_TRACE_STRICT_MODE_OPTIMIZATIONS``.
This option adds more advanced injection attack detection to your workflow, but it is not enabled by default.
The reason for this is the additional considerations for end user applications when using this option, detailed below:
- This option is intended for Charlie workflow only.
- It is recommended to advise users to avoid taking pictures outside in direct sunlight. Direct sunlight may increase errors for live users.
- Enabling this option requires additional time to process data after the subject's photo is taken. To ensure a smooth end user experience, a ``POST_CAPTURE_PROCESSING`` status will be provided. While this is occurring, it is advised to update the UI display as the SDK will no longer be displaying the camera feed.
This guide describes how to enable strict mode optimizations and how to handle the extra processing time on the UI by displaying an animation during the ``POST_CAPTURE_PROCESSING`` phase.
Enabling Strict Mode Optimizations
----------------------------------
Before starting the Face Capture process, set the ``LIGHT_TRACE_STRICT_MODE_OPTIMIZATIONS`` workflow property to ``true``.
The default value is ``false``.
.. code-block:: KOTLIN
:caption: *Enable Strict Mode Optimizations*
:name: enableStrictModeOptimizations
workflow?.setPropertyBool(
WorkflowProperty.LIGHT_TRACE_STRICT_MODE_OPTIMIZATIONS,
true
)
.. note::
When ``LIGHT_TRACE_STRICT_MODE_OPTIMIZATIONS`` is enabled, expect an additional ~1 second delay on the ``CaptureSessionStatus.POST_CAPTURE_PROCESSING`` callback before the status transitions to ``COMPLETED``.
To improve the user experience during this delay, it is recommended to display an animation (e.g. a progress indicator followed by a checkmark).
Displaying an Animation During Post-Capture Processing
------------------------------------------------------
The flow is:
- While the status is ``POST_CAPTURE_PROCESSING`` — show a progress animation.
- When the status becomes ``COMPLETED`` — hide the progress and play a checkmark animation; finalize the capture when the animation ends.
Drawable Resources
^^^^^^^^^^^^^^^^^^
res/drawable/ic_check.xml
"""""""""""""""""""""""""
The static checkmark vector.
.. code-block:: XML
:caption: *res/drawable/ic_check.xml*
:name: icCheckXml
res/animator/check_animator.xml
"""""""""""""""""""""""""""""""
Animates ``trimPathEnd`` so the check is drawn stroke-by-stroke.
.. code-block:: XML
:caption: *res/animator/check_animator.xml*
:name: checkAnimatorXml
res/drawable/animated_check.xml
"""""""""""""""""""""""""""""""
Binds the animator to the check path inside the vector.
.. code-block:: XML
:caption: *res/drawable/animated_check.xml*
:name: animatedCheckXml
Layout
^^^^^^
Place a progress indicator and an ``ImageView`` for the checkmark inside your capture layout:
.. code-block:: XML
:caption: *Capture Layout*
:name: captureLayout
Activity Logic
^^^^^^^^^^^^^^
Inside your capture activity, react to the polling status callbacks.
While in ``POST_CAPTURE_PROCESSING``, show the progress; on ``COMPLETED``, play the checkmark animation and only finalize when it ends.
.. code-block:: KOTLIN
:caption: *Handle Polling Status Callbacks*
:name: handlePollingStatusCallbacks
private var isPostProcessingVisible = false
private var isCompletedHandled = false
override fun onPollingStatusListener(
status: CaptureSessionStatus,
frame: ByteArray?,
feedback: AutoCaptureFeedback?
) {
when (status) {
CaptureSessionStatus.CAPTURING -> processCurrentData(frame, feedback)
CaptureSessionStatus.POST_CAPTURE_PROCESSING -> showPostProcessing()
CaptureSessionStatus.COMPLETED -> playCheckmarkThenEnd()
else -> Unit
}
}
private fun showPostProcessing() {
if (isCompletedHandled || isPostProcessingVisible) return
isPostProcessingVisible = true
binding.imgCheckmark.isVisible = false
binding.postProcessingProgress.isVisible = true
}
private fun playCheckmarkThenEnd() {
if (isCompletedHandled) return
isCompletedHandled = true
isPostProcessingVisible = false
runOnUiThread {
binding.postProcessingProgress.isVisible = false
binding.imgCheckmark.isVisible = true
}
val checkDrawable = AnimatedVectorDrawableCompat.create(
binding.root.context,
R.drawable.animated_check
)
if (checkDrawable == null) {
onCaptureEnd()
return
}
runOnUiThread {
binding.imgCheckmark.setImageDrawable(checkDrawable)
checkDrawable.registerAnimationCallback(object : Animatable2Compat.AnimationCallback() {
override fun onAnimationEnd(drawable: Drawable?) {
binding.imgCheckmark.post {
checkDrawable.clearAnimationCallbacks()
onCaptureEnd()
}
}
})
checkDrawable.start()
}
}
Required Imports
^^^^^^^^^^^^^^^^
.. code-block:: KOTLIN
:caption: *Required Imports*
:name: requiredImports
import androidx.core.view.isVisible
import androidx.vectordrawable.graphics.drawable.Animatable2Compat
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
Guard Flags
^^^^^^^^^^^
Two flags prevent double-handling of status callbacks, which can arrive multiple times:
- ``isPostProcessingVisible`` — ensures the progress UI is only shown once per session.
- ``isCompletedHandled`` — ensures the completion animation and ``onCaptureEnd()`` run only once, even if ``COMPLETED`` is delivered repeatedly.