aws-amplify / aws-amplify/amplify-ui-android

FaceLivenessDetector fails on Android 8 (API 26-27): "no front facing camera detected" on devices with a working front camera

Open
#317 1 comment 0 reactions 0 assignees View on GitHub
bug liveness
Dominant language
Kotlin
Stars
25
Forks
18
Avg merge
7d 3h
Merged PRs (30d)
1

Description

### Before creating a new issue, please confirm:

- [x] I have [searched for duplicate or closed issues](https://github.com/aws-amplify/amplify-ui-android/issues?q=is%3Aissue+).
- [x] I have read the guide for [submitting bug reports](https://github.com/aws-amplify/amplify-ui-android/blob/main/CONTRIBUTING.md#reporting-bugsfeature-requests).

### Which UI component?

Liveness

### Gradle script dependencies

implementation "com.amplifyframework.ui:liveness:$rootProject.properties.aws_liveness"

### Environment information

```
# Put output below this line

## Environment

- **Liveness SDK version:** `com.amplifyframework.ui:liveness:1.7.0` (also confirmed on `1.10.0`)
- **CameraX version (transitive):** `androidx.camera:camera-*:1.4.2`
- **Affected Android version:** Android 8.0 / 8.1 (API 26-27)
- **Not affected:** Android 9+ (API 28+)
- **Previous working version:** `com.amplifyframework.ui:liveness:1.5.0` (worked on the same device)

```

### Please include any relevant guides or documentation you're referencing

_No response_

### Describe the bug

# FaceLivenessDetector fails on Android 8 (API 26-27): "no front facing camera detected" on devices with a working front camera

## Description

`FaceLivenessDetector` throws `FaceLivenessDetectionException` with the message _"A front facing camera is required but no front facing camera detected"_ on certain Android 8 (API 26-27) devices that have a fully functional front-facing camera.

The root cause is that `LivenessCoordinator` relies on `ProcessCameraProvider.hasCamera(CameraSelector.DEFAULT_FRONT_CAMERA)` to detect the front camera. `CameraSelector.DEFAULT_FRONT_CAMERA` internally checks `CameraCharacteristics.LENS_FACING == LENS_FACING_FRONT (0)`. On affected Android 8 devices, the Camera2 HAL incorrectly reports **both** cameras (front and back) as `LENS_FACING_BACK (1)`, causing the check to fail.

## Relevant SDK code

`LivenessCoordinator.kt`, `launchCamera()` method:

```kotlin
val (chosenCamera, orientation) = when (camera) {
Camera.Front -> Pair(CameraSelector.DEFAULT_FRONT_CAMERA, "front")
Camera.Back -> Pair(CameraSelector.DEFAULT_BACK_CAMERA, "back")
}

if (this.hasCamera(chosenCamera)) {
bindToLifecycle(lifecycleOwner, chosenCamera, preview, analysis)
} else {
// Error: "A front facing camera is required but no front facing camera detected."
val faceLivenessException = FaceLivenessDetectionException(
"A $orientation facing camera is required but no $orientation facing camera detected.",
"Enable a $orientation facing camera."
)
processSessionError(faceLivenessException, true)
}
```

## Evidence

We verified the issue by querying `CameraManager` directly on the affected device:

```kotlin
val cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
val ids = cameraManager.cameraIdList
// ids = ["0", "1"] — two cameras exist

for (id in ids) {
val facing = cameraManager.getCameraCharacteristics(id)
.get(CameraCharacteristics.LENS_FACING)
Log.i(TAG, "camera id=$id, LENS_FACING=$facing")
}
```

**Output on affected Android 8 device:**
```
camera id=0, LENS_FACING=1 // LENS_FACING_BACK
camera id=1, LENS_FACING=1 // LENS_FACING_BACK ← should be 0 (LENS_FACING_FRONT)
```

Both cameras report `LENS_FACING_BACK(1)` despite the device having a working front camera (confirmed by other camera apps). The Camera2 HAL on this device is broken.

**Camera permission** is granted (`checkSelfPermission == PERMISSION_GRANTED`) at the time of the check.

## Expected behavior

`FaceLivenessDetector` should successfully open the front camera and start the liveness session on devices that have a physically working front camera.

## Actual behavior

`FaceLivenessDetector` immediately fails with:
```
FaceLivenessDetectionException: A front facing camera is required but no front facing camera detected.
```

## Suggested fix

Consider adding a fallback in `LivenessCoordinator.launchCamera()` for cases where `ProcessCameraProvider.hasCamera(CameraSelector.DEFAULT_FRONT_CAMERA)` returns `false` but the device has multiple cameras. Possible approaches:

1. **Fallback to camera count heuristic:** If `hasCamera(DEFAULT_FRONT_CAMERA)` fails and `cameraIdList.size >= 2`, attempt to bind with `DEFAULT_FRONT_CAMERA` anyway — CameraX may still be able to open it even if `hasCamera` reports false.

2. **Use a custom CameraSelector** that selects by camera ID rather than `LENS_FACING`:
```kotlin
// Fallback: try camera ID "1" which is typically front on most devices
val fallbackSelector = CameraSelector.Builder()
.addCameraFilter { cameras -> cameras.filter { it.cameraId == "1" } }
.build()
```

3. **Document minimum supported API level:** If Android 8 support is not feasible due to Camera2 HAL inconsistencies, consider documenting API 28 (Android 9) as the minimum supported version for `FaceLivenessDetector` and failing gracefully with a clear error message.

## Current workaround

We gate the liveness feature to Android 9+ (API 28):

```kotlin
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
// Show error: face liveness not supported on this device
return
}
```

## Steps to reproduce

1. Use an Android 8 device where Camera2 HAL reports incorrect `LENS_FACING` for the front camera
2. Grant camera permission
3. Launch `FaceLivenessDetector` with a valid session ID
4. Observe the error in `onError` callback

### Reproduction steps (if applicable)

_No response_

### Code Snippet

```kotlin
// Put your code below this line.

```

### Log output

```
// Put your logs below this line

```

### Configuration File

_No response_

### Additional information and screenshots

_No response_

Contributor guide

Open the contributing guide

Research direction

Start in LivenessCoordinator.kt at launchCamera(), then trace the CameraX ProcessCameraProvider.hasCamera and camera-binding path for the front selector. Reproduce on an affected Android 8 device and verify that a working front camera can start the liveness session without the no-front-camera error, while preserving behavior on Android 9+.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, kotlin
Domain
mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.