From f13bf5ea4b22107f1d0086411074997476810cb7 Mon Sep 17 00:00:00 2001 From: Sebastian Villena <97059974+ruisebas@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:55:48 -0400 Subject: [PATCH] feat: Adding new error when the camera is not available even though permissions were granted. (#163) --- HostApp/HostApp/Views/ExampleLivenessView.swift | 4 ++++ HostApp/HostApp/Views/LivenessCheckErrorContentView.swift | 5 +++++ .../Views/Liveness/FaceLivenessDetectionError.swift | 6 ++++++ .../Views/Liveness/FaceLivenessDetectionView.swift | 2 ++ .../Views/Liveness/FaceLivenessDetectionViewModel.swift | 4 ++-- .../FaceLiveness/Views/Liveness/LivenessStateMachine.swift | 1 + 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/HostApp/HostApp/Views/ExampleLivenessView.swift b/HostApp/HostApp/Views/ExampleLivenessView.swift index 39407c89..7114dcdf 100644 --- a/HostApp/HostApp/Views/ExampleLivenessView.swift +++ b/HostApp/HostApp/Views/ExampleLivenessView.swift @@ -45,6 +45,8 @@ struct ExampleLivenessView: View { viewModel.presentationState = .error(.countdownFaceTooClose) case .failure(.invalidSignature): viewModel.presentationState = .error(.invalidSignature) + case .failure(.cameraNotAvailable): + viewModel.presentationState = .error(.cameraNotAvailable) default: viewModel.presentationState = .liveness } @@ -74,6 +76,8 @@ struct ExampleLivenessView: View { LivenessCheckErrorContentView.failedDuringCountdown case .invalidSignature: LivenessCheckErrorContentView.invalidSignature + case .cameraNotAvailable: + LivenessCheckErrorContentView.cameraNotAvailable default: LivenessCheckErrorContentView.unexpected } diff --git a/HostApp/HostApp/Views/LivenessCheckErrorContentView.swift b/HostApp/HostApp/Views/LivenessCheckErrorContentView.swift index 3357aa7a..866c2c1c 100644 --- a/HostApp/HostApp/Views/LivenessCheckErrorContentView.swift +++ b/HostApp/HostApp/Views/LivenessCheckErrorContentView.swift @@ -55,6 +55,11 @@ extension LivenessCheckErrorContentView { name: "The signature on the request is invalid.", description: "Ensure the device time is correct and try again." ) + + static let cameraNotAvailable = LivenessCheckErrorContentView( + name: "The camera could not be started.", + description: "There might be a hardware issue with the camera." + ) } struct LivenessCheckErrorContentView_Previews: PreviewProvider { diff --git a/Sources/FaceLiveness/Views/Liveness/FaceLivenessDetectionError.swift b/Sources/FaceLiveness/Views/Liveness/FaceLivenessDetectionError.swift index a19cfd57..e90a6f06 100644 --- a/Sources/FaceLiveness/Views/Liveness/FaceLivenessDetectionError.swift +++ b/Sources/FaceLiveness/Views/Liveness/FaceLivenessDetectionError.swift @@ -126,6 +126,12 @@ public struct FaceLivenessDetectionError: Error, Equatable { recoverySuggestion: "Ensure the device time is correct and try again." ) + public static let cameraNotAvailable = FaceLivenessDetectionError( + code: 18, + message: "The camera is not available.", + recoverySuggestion: "There might be a hardware issue." + ) + public static func == (lhs: FaceLivenessDetectionError, rhs: FaceLivenessDetectionError) -> Bool { lhs.code == rhs.code } diff --git a/Sources/FaceLiveness/Views/Liveness/FaceLivenessDetectionView.swift b/Sources/FaceLiveness/Views/Liveness/FaceLivenessDetectionView.swift index bc4e47e8..ee45a9d0 100644 --- a/Sources/FaceLiveness/Views/Liveness/FaceLivenessDetectionView.swift +++ b/Sources/FaceLiveness/Views/Liveness/FaceLivenessDetectionView.swift @@ -205,6 +205,8 @@ public struct FaceLivenessDetectorView: View { return .faceInOvalMatchExceededTimeLimitError case .socketClosed: return .socketClosed + case .cameraNotAvailable: + return .cameraNotAvailable default: return .cameraPermissionDenied } diff --git a/Sources/FaceLiveness/Views/Liveness/FaceLivenessDetectionViewModel.swift b/Sources/FaceLiveness/Views/Liveness/FaceLivenessDetectionViewModel.swift index b1a95f36..7f834cb2 100644 --- a/Sources/FaceLiveness/Views/Liveness/FaceLivenessDetectionViewModel.swift +++ b/Sources/FaceLiveness/Views/Liveness/FaceLivenessDetectionViewModel.swift @@ -338,8 +338,8 @@ class FaceLivenessDetectionViewModel: ObservableObject { switch captureSessionError { case LivenessCaptureSessionError.cameraUnavailable, LivenessCaptureSessionError.deviceInputUnavailable: - - livenessError = .missingVideoPermission + let authStatus = AVCaptureDevice.authorizationStatus(for: .video) + livenessError = authStatus == .authorized ? .cameraNotAvailable : .missingVideoPermission case LivenessCaptureSessionError.captureSessionOutputUnavailable, LivenessCaptureSessionError.captureSessionInputUnavailable: diff --git a/Sources/FaceLiveness/Views/Liveness/LivenessStateMachine.swift b/Sources/FaceLiveness/Views/Liveness/LivenessStateMachine.swift index 872c7ee6..c59629c9 100644 --- a/Sources/FaceLiveness/Views/Liveness/LivenessStateMachine.swift +++ b/Sources/FaceLiveness/Views/Liveness/LivenessStateMachine.swift @@ -159,6 +159,7 @@ struct LivenessStateMachine { static let couldNotOpenStream = LivenessError(code: 5, webSocketCloseCode: .unexpectedRuntimeError) static let socketClosed = LivenessError(code: 6, webSocketCloseCode: .normalClosure) static let viewResignation = LivenessError(code: 8, webSocketCloseCode: .viewClosure) + static let cameraNotAvailable = LivenessError(code: 9, webSocketCloseCode: .missingVideoPermission) static func == (lhs: LivenessError, rhs: LivenessError) -> Bool { lhs.code == rhs.code