@@ -22,7 +22,6 @@ import androidx.compose.runtime.getValue
22
22
import androidx.compose.runtime.mutableStateOf
23
23
import androidx.compose.runtime.setValue
24
24
import com.amplifyframework.predictions.aws.models.ColorChallenge
25
- import com.amplifyframework.predictions.aws.models.ColorChallengeType
26
25
import com.amplifyframework.predictions.aws.models.FaceTargetChallenge
27
26
import com.amplifyframework.predictions.aws.models.FaceTargetChallengeResponse
28
27
import com.amplifyframework.predictions.aws.models.InitialFaceDetected
@@ -47,15 +46,14 @@ internal data class LivenessState(
47
46
val context : Context ,
48
47
val disableStartView : Boolean ,
49
48
val onCaptureReady : () -> Unit ,
50
- val onFaceDistanceCheckPassed : () -> Unit ,
51
49
val onSessionError : (FaceLivenessDetectionException , Boolean ) -> Unit ,
52
50
val onFinalEventsSent : () -> Unit ,
53
51
) {
54
52
var videoViewportSize: VideoViewportSize ? by mutableStateOf(null )
55
- var livenessCheckState = mutableStateOf<LivenessCheckState >(
53
+ var livenessCheckState by mutableStateOf<LivenessCheckState >(
56
54
LivenessCheckState .Initial ()
57
55
)
58
- var runningFreshness by mutableStateOf(false )
56
+ var faceMatched by mutableStateOf(false )
59
57
var faceGuideRect: RectF ? by mutableStateOf(null )
60
58
var faceMatchPercentage: Float by mutableStateOf(0.25f )
61
59
var initialFaceDistanceCheckPassed by mutableStateOf(false )
@@ -78,7 +76,7 @@ internal data class LivenessState(
78
76
@VisibleForTesting
79
77
var readyToSendFinalEvents = false
80
78
81
- var livenessSessionInfo: FaceLivenessSession ? = null
79
+ var livenessSessionInfo: FaceLivenessSession ? by mutableStateOf( null )
82
80
var faceTargetChallenge: FaceTargetChallenge ? by mutableStateOf(null )
83
81
var colorChallenge: ColorChallenge ? = null
84
82
@@ -89,18 +87,18 @@ internal data class LivenessState(
89
87
}
90
88
91
89
fun onError (stopLivenessSession : Boolean , webSocketCloseCode : WebSocketCloseCode ) {
92
- livenessCheckState.value = LivenessCheckState .Error
90
+ livenessCheckState = LivenessCheckState .Error
93
91
onDestroy(stopLivenessSession, webSocketCloseCode)
94
92
}
95
93
96
94
// Cleans up state when challenge is completed or cancelled.
97
95
// We only send webSocketCloseCode if error encountered.
98
96
fun onDestroy (stopLivenessSession : Boolean , webSocketCloseCode : WebSocketCloseCode ? = null) {
99
- livenessCheckState.value = LivenessCheckState .Error
97
+ livenessCheckState = LivenessCheckState .Error
100
98
faceOvalMatchTimer?.cancel()
101
99
readyForOval = false
102
100
faceGuideRect = null
103
- runningFreshness = false
101
+ faceMatched = false
104
102
if (stopLivenessSession) {
105
103
livenessSessionInfo?.stopSession(webSocketCloseCode?.code)
106
104
}
@@ -112,24 +110,23 @@ internal data class LivenessState(
112
110
.filterIsInstance<FaceTargetChallenge >().firstOrNull()
113
111
colorChallenge = faceLivenessSession.challenges
114
112
.filterIsInstance<ColorChallenge >().firstOrNull()
115
- livenessCheckState.value = LivenessCheckState .Running ()
116
113
readyForOval = true
117
114
}
118
115
119
116
fun onFullChallengeComplete () {
120
117
readyToSendFinalEvents = true
121
118
}
122
119
123
- fun onFreshnessComplete () {
120
+ fun onLivenessChallengeComplete () {
124
121
val faceGuideRect = this .faceGuideRect
125
122
readyForOval = false
126
123
this .faceGuideRect = null
127
- runningFreshness = false
124
+ faceMatched = false
128
125
if (faceMatchOvalEnd == null ) {
129
126
faceMatchOvalEnd = Date ().time
130
127
}
131
128
132
- livenessCheckState.value = if (faceGuideRect != null ) {
129
+ livenessCheckState = if (faceGuideRect != null ) {
133
130
LivenessCheckState .Success (faceGuideRect)
134
131
} else {
135
132
LivenessCheckState .Error
@@ -142,19 +139,19 @@ internal data class LivenessState(
142
139
fun onFrameAvailable (): Boolean {
143
140
if (showingStartView) return false
144
141
145
- return when (val livenessCheckState = livenessCheckState.value ) {
142
+ return when (val livenessCheckState = livenessCheckState) {
146
143
is LivenessCheckState .Error -> false
147
144
is LivenessCheckState .Initial , is LivenessCheckState .Running -> {
148
145
/* *
149
- * Start freshness check if the face has matched oval (we know this if faceMatchOvalStart is not null)
150
- * We trigger this in onFrameAvailable instead of onFrameFaceUpdate in the event the user moved the face
151
- * away from the camera. We want to run this check on every frame if the challenge is in process.
146
+ * Start the challenge checks once the face has matched oval (we know this if faceMatchOvalStart is
147
+ * not null). We trigger this in onFrameAvailable instead of onFrameFaceUpdate in the event the user
148
+ * moved the face away from the camera. We want to run this check on every frame if the challenge is
149
+ * in process.
152
150
*/
153
- if (! runningFreshness && colorChallenge?.challengeType ==
154
- ColorChallengeType .SEQUENTIAL &&
151
+ if (! faceMatched &&
155
152
faceMatchOvalStart?.let { (Date ().time - it) > 1000 } == true
156
153
) {
157
- runningFreshness = true
154
+ faceMatched = true
158
155
}
159
156
true
160
157
}
@@ -164,7 +161,7 @@ internal data class LivenessState(
164
161
165
162
livenessSessionInfo!! .sendChallengeResponseEvent(
166
163
FaceTargetChallengeResponse (
167
- colorChallenge !! .challengeId,
164
+ livenessSessionInfo !! .challengeId,
168
165
livenessCheckState.faceGuideRect,
169
166
Date (faceMatchOvalStart!! ),
170
167
Date (faceMatchOvalEnd!! )
@@ -186,10 +183,10 @@ internal data class LivenessState(
186
183
}
187
184
when (faceCount) {
188
185
0 -> {
189
- if (! initialLocalFaceFound || livenessCheckState.value is LivenessCheckState .Initial ) {
190
- livenessCheckState.value = LivenessCheckState .Initial .withMoveFaceMessage()
191
- } else if (livenessCheckState.value is LivenessCheckState .Running ) {
192
- livenessCheckState.value = LivenessCheckState .Running .withMoveFaceMessage()
186
+ if (! initialLocalFaceFound || livenessCheckState is LivenessCheckState .Initial ) {
187
+ livenessCheckState = LivenessCheckState .Initial .withMoveFaceMessage()
188
+ } else if (livenessCheckState is LivenessCheckState .Running ) {
189
+ livenessCheckState = LivenessCheckState .Running .withMoveFaceMessage()
193
190
}
194
191
}
195
192
1 -> {
@@ -198,10 +195,10 @@ internal data class LivenessState(
198
195
}
199
196
}
200
197
else -> {
201
- if (! initialLocalFaceFound || livenessCheckState.value is LivenessCheckState .Initial ) {
202
- livenessCheckState.value = LivenessCheckState .Initial .withMultipleFaceMessage()
203
- } else if (livenessCheckState.value is LivenessCheckState .Running ) {
204
- livenessCheckState.value = LivenessCheckState .Running .withMultipleFaceMessage()
198
+ if (! initialLocalFaceFound || livenessCheckState is LivenessCheckState .Initial ) {
199
+ livenessCheckState = LivenessCheckState .Initial .withMultipleFaceMessage()
200
+ } else if (livenessCheckState is LivenessCheckState .Running ) {
201
+ livenessCheckState = LivenessCheckState .Running .withMultipleFaceMessage()
205
202
}
206
203
}
207
204
}
@@ -226,11 +223,10 @@ internal data class LivenessState(
226
223
LivenessCoordinator .TARGET_WIDTH , LivenessCoordinator .TARGET_HEIGHT
227
224
)
228
225
if (faceDistance >= FaceDetector .INITIAL_FACE_DISTANCE_THRESHOLD ) {
229
- livenessCheckState.value =
226
+ livenessCheckState =
230
227
LivenessCheckState .Initial .withMoveFaceFurtherAwayMessage()
231
228
} else {
232
229
initialFaceDistanceCheckPassed = true
233
- onFaceDistanceCheckPassed()
234
230
}
235
231
}
236
232
@@ -240,7 +236,7 @@ internal data class LivenessState(
240
236
onCaptureReady()
241
237
livenessSessionInfo!! .sendChallengeResponseEvent(
242
238
InitialFaceDetected (
243
- colorChallenge !! .challengeId,
239
+ livenessSessionInfo !! .challengeId,
244
240
face.faceRect,
245
241
Date (face.timestamp)
246
242
)
@@ -278,11 +274,11 @@ internal data class LivenessState(
278
274
faceOvalPosition == FaceDetector .FaceOvalPosition .MATCHED
279
275
280
276
if (detectedFaceMatchedOval) {
281
- livenessCheckState.value = LivenessCheckState .Running .withFaceOvalPosition(
277
+ livenessCheckState = LivenessCheckState .Running .withFaceOvalPosition(
282
278
FaceDetector .FaceOvalPosition .MATCHED
283
279
)
284
280
} else {
285
- livenessCheckState.value = LivenessCheckState .Running .withFaceOvalPosition(
281
+ livenessCheckState = LivenessCheckState .Running .withFaceOvalPosition(
286
282
faceOvalPosition
287
283
)
288
284
}
@@ -314,6 +310,7 @@ internal data class LivenessState(
314
310
}
315
311
316
312
fun onStartViewComplete () {
313
+ livenessCheckState = LivenessCheckState .Running ()
317
314
showingStartView = false
318
315
}
319
316
}
0 commit comments