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.

Enable Strict Mode Optimizations
   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.

res/drawable/ic_check.xml
   <vector xmlns:android="http://schemas.android.com/apk/res/android"
       android:width="96dp"
       android:height="96dp"
       android:viewportWidth="96"
       android:viewportHeight="96">

       <path
           android:name="check"
           android:pathData="M28,50 L42,64 L70,32"
           android:fillColor="@android:color/transparent"
           android:strokeColor="@color/colorGreen"
           android:strokeWidth="6"
           android:strokeLineCap="round"
           android:strokeLineJoin="round"
           android:trimPathEnd="0" />
   </vector>

res/animator/check_animator.xml

Animates trimPathEnd so the check is drawn stroke-by-stroke.

res/animator/check_animator.xml
   <objectAnimator
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:propertyName="trimPathEnd"
       android:duration="1000"
       android:valueFrom="0"
       android:valueTo="1"
       android:valueType="floatType" />

res/drawable/animated_check.xml

Binds the animator to the check path inside the vector.

res/drawable/animated_check.xml
   <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
       android:drawable="@drawable/ic_check">

       <target
           android:name="check"
           android:animation="@animator/check_animator" />
   </animated-vector>

Layout

Place a progress indicator and an ImageView for the checkmark inside your capture layout:

Capture Layout
   <ProgressBar
       android:id="@+id/postProcessingProgress"
       android:layout_width="64dp"
       android:layout_height="64dp"
       android:visibility="gone" />

   <ImageView
       android:id="@+id/imgCheckmark"
       android:layout_width="96dp"
       android:layout_height="96dp"
       android:visibility="gone" />

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.

Handle Polling Status Callbacks
   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

Required Imports
   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.