Aperture: Add a Camera2 info class wrapper

* And use that for camera facing

Change-Id: I045a04f52181d114923ce49d8c97d6c9c53c4e4c
diff --git a/app/src/main/java/org/lineageos/aperture/MainActivity.kt b/app/src/main/java/org/lineageos/aperture/MainActivity.kt
index a7c4119..a162c7e 100644
--- a/app/src/main/java/org/lineageos/aperture/MainActivity.kt
+++ b/app/src/main/java/org/lineageos/aperture/MainActivity.kt
@@ -33,6 +33,7 @@
 import org.lineageos.aperture.databinding.ActivityMainBinding
 import org.lineageos.aperture.utils.CameraFacing
 import org.lineageos.aperture.utils.CameraMode
+import org.lineageos.aperture.utils.PhysicalCamera
 import org.lineageos.aperture.utils.SharedPreferencesUtils
 import java.text.SimpleDateFormat
 import java.util.Locale
@@ -48,7 +49,7 @@
     private lateinit var cameraExecutor: ExecutorService
 
     private lateinit var camera: Camera
-    private lateinit var cameraFacing: CameraFacing
+    private lateinit var physicalCamera: PhysicalCamera
 
     private lateinit var cameraMode: CameraMode
     private var extensionMode: Int = ExtensionMode.NONE
@@ -59,6 +60,7 @@
     private var videoCapture: VideoCapture<Recorder>? = null
     private var recording: Recording? = null
 
+    @androidx.camera.camera2.interop.ExperimentalCamera2Interop
     @androidx.camera.core.ExperimentalZeroShutterLag
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -98,6 +100,7 @@
         cameraExecutor.shutdown()
     }
 
+    @androidx.camera.camera2.interop.ExperimentalCamera2Interop
     @androidx.camera.core.ExperimentalZeroShutterLag
     override fun onRequestPermissionsResult(
         requestCode: Int, permissions: Array<String>, grantResults:
@@ -255,6 +258,7 @@
     /**
      * Prepare CameraProvider and other one-time init objects, must only be called from onCreate
      */
+    @androidx.camera.camera2.interop.ExperimentalCamera2Interop
     @androidx.camera.core.ExperimentalZeroShutterLag
     private fun initCamera() {
         val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
@@ -274,6 +278,7 @@
     /**
      * Rebind cameraProvider use cases
      */
+    @androidx.camera.camera2.interop.ExperimentalCamera2Interop
     @androidx.camera.core.ExperimentalZeroShutterLag
     private fun bindCameraUseCases() {
         // Unbind previous use cases
@@ -286,10 +291,10 @@
         val sharedPreferences = getSharedPreferences()
 
         // Select front/back camera
-        cameraFacing = SharedPreferencesUtils.getLastCameraFacing(sharedPreferences)
-        var cameraSelector = when (cameraFacing) {
+        var cameraSelector = when (SharedPreferencesUtils.getLastCameraFacing(sharedPreferences)) {
             CameraFacing.FRONT -> CameraSelector.DEFAULT_FRONT_CAMERA
             CameraFacing.BACK -> CameraSelector.DEFAULT_BACK_CAMERA
+            else -> CameraSelector.DEFAULT_BACK_CAMERA
         }
 
         // Get the user selected effect
@@ -344,11 +349,13 @@
                 CameraMode.PHOTO -> imageCapture
                 CameraMode.VIDEO -> videoCapture
             })
+        physicalCamera = PhysicalCamera(camera.cameraInfo)
     }
 
     /**
      * Change the current camera mode and restarts the stream
      */
+    @androidx.camera.camera2.interop.ExperimentalCamera2Interop
     @androidx.camera.core.ExperimentalZeroShutterLag
     private fun changeCameraMode(cameraMode: CameraMode) {
         if (!canRestartCamera())
@@ -364,16 +371,19 @@
     /**
      * Cycle between cameras
      */
+    @androidx.camera.camera2.interop.ExperimentalCamera2Interop
     @androidx.camera.core.ExperimentalZeroShutterLag
     private fun flipCamera() {
         if (!canRestartCamera())
             return
 
-        SharedPreferencesUtils.setLastCameraFacing(getSharedPreferences(), when(cameraFacing) {
-            // We can definitely do it better
-            CameraFacing.FRONT -> CameraFacing.BACK
-            CameraFacing.BACK -> CameraFacing.FRONT
-        })
+        SharedPreferencesUtils.setLastCameraFacing(
+            getSharedPreferences(), when(physicalCamera.getCameraFacing()) {
+                // We can definitely do it better
+                CameraFacing.FRONT -> CameraFacing.BACK
+                CameraFacing.BACK -> CameraFacing.FRONT
+                else -> CameraFacing.BACK
+            })
 
         bindCameraUseCases()
     }
@@ -431,6 +441,7 @@
     /**
      * Set a photo effect and restart the camera
      */
+    @androidx.camera.camera2.interop.ExperimentalCamera2Interop
     @androidx.camera.core.ExperimentalZeroShutterLag
     private fun setExtensionMode(extensionMode: Int) {
         if (!canRestartCamera())
@@ -464,6 +475,7 @@
     /**
      * Cycle between supported photo camera effects
      */
+    @androidx.camera.camera2.interop.ExperimentalCamera2Interop
     @androidx.camera.core.ExperimentalZeroShutterLag
     private fun cyclePhotoEffects() {
         if (!canRestartCamera())
diff --git a/app/src/main/java/org/lineageos/aperture/utils/CameraFacing.kt b/app/src/main/java/org/lineageos/aperture/utils/CameraFacing.kt
index 837175c..3e81326 100644
--- a/app/src/main/java/org/lineageos/aperture/utils/CameraFacing.kt
+++ b/app/src/main/java/org/lineageos/aperture/utils/CameraFacing.kt
@@ -1,6 +1,8 @@
 package org.lineageos.aperture.utils
 
 enum class CameraFacing {
+    UNKNOWN,
     FRONT,
     BACK,
+    EXTERNAL,
 }
diff --git a/app/src/main/java/org/lineageos/aperture/utils/PhysicalCamera.kt b/app/src/main/java/org/lineageos/aperture/utils/PhysicalCamera.kt
new file mode 100644
index 0000000..96e3d71
--- /dev/null
+++ b/app/src/main/java/org/lineageos/aperture/utils/PhysicalCamera.kt
@@ -0,0 +1,46 @@
+package org.lineageos.aperture.utils
+
+import android.hardware.camera2.CameraCharacteristics
+import androidx.camera.camera2.interop.Camera2CameraInfo
+import androidx.camera.core.CameraInfo
+
+/**
+ * Class representing a physical device camera
+ */
+@androidx.camera.camera2.interop.ExperimentalCamera2Interop
+class PhysicalCamera(private val cameraInfo: CameraInfo) {
+    private val camera2CameraInfo = Camera2CameraInfo.from(cameraInfo)
+
+    /**
+     * Return a CameraX's CameraInfo object
+     */
+    fun getCameraInfo(): CameraInfo {
+        return cameraInfo
+    }
+
+    /**
+     * Return a CameraX's Camera2CameraInfo object
+     */
+    fun getCamera2CameraInfo(): Camera2CameraInfo {
+        return camera2CameraInfo
+    }
+
+    /**
+     * Returns a Camera2 compatible camera ID
+     */
+    fun getCameraId(): Int {
+        return camera2CameraInfo.cameraId.toInt()
+    }
+
+    /**
+     * Return the facing of the camera
+     */
+    fun getCameraFacing(): CameraFacing {
+        return when (camera2CameraInfo.getCameraCharacteristic(CameraCharacteristics.LENS_FACING)) {
+            CameraCharacteristics.LENS_FACING_FRONT -> CameraFacing.FRONT
+            CameraCharacteristics.LENS_FACING_BACK -> CameraFacing.BACK
+            CameraCharacteristics.LENS_FACING_EXTERNAL -> CameraFacing.EXTERNAL
+            else -> CameraFacing.UNKNOWN
+        }
+    }
+}
diff --git a/app/src/main/java/org/lineageos/aperture/utils/SharedPreferencesUtils.kt b/app/src/main/java/org/lineageos/aperture/utils/SharedPreferencesUtils.kt
index 52c4f6b..aeddec6 100644
--- a/app/src/main/java/org/lineageos/aperture/utils/SharedPreferencesUtils.kt
+++ b/app/src/main/java/org/lineageos/aperture/utils/SharedPreferencesUtils.kt
@@ -15,8 +15,10 @@
         fun getLastCameraFacing(sharedPreferences: SharedPreferences): CameraFacing {
             return when (sharedPreferences.getString(
                 LAST_CAMERA_FACING_KEY, LAST_CAMERA_FACING_DEFAULT)) {
+                "unknown" -> CameraFacing.UNKNOWN
                 "front" -> CameraFacing.FRONT
                 "back" -> CameraFacing.BACK
+                "external" -> CameraFacing.EXTERNAL
                 // Default to back
                 else -> CameraFacing.BACK
             }
@@ -25,8 +27,10 @@
         fun setLastCameraFacing(sharedPreferences: SharedPreferences, value: CameraFacing) {
             sharedPreferences.edit {
                 putString(LAST_CAMERA_FACING_KEY, when (value) {
+                    CameraFacing.UNKNOWN -> "unknown"
                     CameraFacing.FRONT -> "front"
                     CameraFacing.BACK -> "back"
+                    CameraFacing.EXTERNAL -> "external"
                 })
             }
         }