diff --git a/app/src/main/java/org/fdroid/fdroid/views/swap/device/camera/CameraCharacteristicsChecker.java b/app/src/main/java/org/fdroid/fdroid/views/swap/device/camera/CameraCharacteristicsChecker.java new file mode 100644 index 000000000..4a66c5eba --- /dev/null +++ b/app/src/main/java/org/fdroid/fdroid/views/swap/device/camera/CameraCharacteristicsChecker.java @@ -0,0 +1,20 @@ +package org.fdroid.fdroid.views.swap.device.camera; + +import android.content.Context; + +public abstract class CameraCharacteristicsChecker { + public static CameraCharacteristicsChecker getInstance(final Context context) { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + return new CameraCharacteristicsMinApiLevel21(context); + } else + return new CameraCharacteristicsMaxApiLevel20(); + } + + public abstract boolean hasAutofocus(); + + class FDroidDeviceException extends Exception { + FDroidDeviceException(final String message, final Throwable cause) { + super(message, cause); + } + } +} diff --git a/app/src/main/java/org/fdroid/fdroid/views/swap/device/camera/CameraCharacteristicsMaxApiLevel20.java b/app/src/main/java/org/fdroid/fdroid/views/swap/device/camera/CameraCharacteristicsMaxApiLevel20.java new file mode 100644 index 000000000..38d31fc96 --- /dev/null +++ b/app/src/main/java/org/fdroid/fdroid/views/swap/device/camera/CameraCharacteristicsMaxApiLevel20.java @@ -0,0 +1,50 @@ +package org.fdroid.fdroid.views.swap.device.camera; + +import android.hardware.Camera; +import android.util.Log; + +import java.util.List; + +public class CameraCharacteristicsMaxApiLevel20 extends CameraCharacteristicsChecker { + + private static final String TAG = "CameraCharMaxApiLevel20"; + + protected CameraCharacteristicsMaxApiLevel20() { + } + + @Override + public boolean hasAutofocus() { + boolean hasAutofocus = false; + try { + hasAutofocus = hasDeviceAutofocusCapability(); + } catch (FDroidDeviceException e) { + Log.e(TAG, e.getMessage(), e); + } + return hasAutofocus; + } + + private boolean hasDeviceAutofocusCapability() throws FDroidDeviceException { + try { + final int numberOfCameras = Camera.getNumberOfCameras(); + if (numberOfCameras == 0) { + Log.i(TAG, "No camera on device"); + return false; + } + + boolean hasAutofocus = false; + for (int cameraId = 0; cameraId < numberOfCameras; cameraId++) { + Camera camera = Camera.open(cameraId); + Camera.Parameters parameters = camera.getParameters(); + List availableAFModes = parameters.getSupportedFocusModes(); + hasAutofocus = availableAFModes.contains(Camera.Parameters.FOCUS_MODE_AUTO); + } + + return hasAutofocus; + } catch (Exception e) { + String msg = "Exception accessing device camera"; + Log.e(TAG, msg, e); + throw new FDroidDeviceException(msg, e); + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/fdroid/fdroid/views/swap/device/camera/CameraCharacteristicsMinApiLevel21.java b/app/src/main/java/org/fdroid/fdroid/views/swap/device/camera/CameraCharacteristicsMinApiLevel21.java new file mode 100644 index 000000000..8992fc050 --- /dev/null +++ b/app/src/main/java/org/fdroid/fdroid/views/swap/device/camera/CameraCharacteristicsMinApiLevel21.java @@ -0,0 +1,112 @@ +package org.fdroid.fdroid.views.swap.device.camera; + +import android.annotation.TargetApi; +import android.content.Context; +import android.hardware.camera2.CameraAccessException; +import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CameraManager; +import android.os.Build; +import android.support.annotation.NonNull; +import android.util.Log; + +@TargetApi(Build.VERSION_CODES.LOLLIPOP) +public class CameraCharacteristicsMinApiLevel21 extends CameraCharacteristicsChecker { + + private static final String TAG = "CameraCharMinApiLevel21"; + final private CameraManager cameraManager; + + + protected CameraCharacteristicsMinApiLevel21(final Context context) { + this.cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); + } + + @Override + public boolean hasAutofocus() { + boolean hasAutofocus = false; + try { + hasAutofocus = hasDeviceAutofocus(); + } catch (FDroidDeviceException e) { + Log.e(TAG, e.getMessage(), e); + } + return hasAutofocus; + } + + private boolean hasDeviceAutofocus() throws FDroidDeviceException { + try { + boolean deviceHasAutofocus = false; + final String[] cameraIdList = getCameraIdList(); + + for (final String cameraId : cameraIdList) { + if (isLensFacingBack(cameraId)) { + deviceHasAutofocus = testAutofocusModeForCamera(cameraId); + break; + } + } + return deviceHasAutofocus; + } catch (Exception e) { + Log.e(TAG, e.getMessage(), e); + throw new FDroidDeviceException("Exception accessing the camera list", e); + } + + } + + @NonNull + private String[] getCameraIdList() throws FDroidDeviceException { + try { + return cameraManager.getCameraIdList(); + } catch (CameraAccessException e) { + Log.e(TAG, e.getMessage(), e); + throw new FDroidDeviceException("Exception accessing the camera list", e); + } + } + + private boolean isLensFacingBack(final String cameraId) throws FDroidDeviceException { + final Integer lensFacing = getCameraCharacteristics(cameraId).get(CameraCharacteristics.LENS_FACING); + + return lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK; + } + + @NonNull + private CameraCharacteristics getCameraCharacteristics(final String cameraId) throws FDroidDeviceException { + try { + return cameraManager.getCameraCharacteristics(cameraId); + } catch (CameraAccessException e) { + Log.e(TAG, e.getMessage(), e); + throw new FDroidDeviceException("Exception accessing the camera id = " + cameraId, e); + } + + } + + private boolean testAutofocusModeForCamera(final String cameraId) throws FDroidDeviceException { + try { + boolean hasAutofocusMode = false; + final int[] autoFocusModes = getAvailableAFModes(cameraId); + if (autoFocusModes != null) { + hasAutofocusMode = testAvailableMode(autoFocusModes); + } + + return hasAutofocusMode; + } catch (FDroidDeviceException e) { + Log.e(TAG, e.getMessage(), e); + throw new FDroidDeviceException("Exception accessing the camera id = " + cameraId, e); + } + } + + private int[] getAvailableAFModes(final String cameraId) throws FDroidDeviceException { + return getCameraCharacteristics(cameraId).get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES); + } + + private boolean testAvailableMode(final int[] autoFocusModes) { + boolean hasAutofocusMode = false; + for (final int mode : autoFocusModes) { + boolean afMode = isAutofocus(mode); + hasAutofocusMode |= afMode; + } + return hasAutofocusMode; + } + + private boolean isAutofocus(final int mode) { + return mode != android.hardware.camera2.CameraMetadata.CONTROL_AF_MODE_OFF; + } + +}