Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ebbff02a authored by Mohammed Althaf T's avatar Mohammed Althaf T 😊
Browse files

camera: import CameraID tools

- Imported from https://github.com/vibhorSrv/CameraIDs
- Also converted to kotlin

Change-Id: I5b5fdb76ffea16da6a76596e53da5d702a89e71e
parent c6cde459
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
apply plugin: 'com.android.application'
apply plugin: 'org.jetbrains.kotlin.android'

android {
    compileSdkVersion 31
@@ -11,7 +12,7 @@ android {

    defaultConfig {
        applicationId "foundation.e.camera"
        minSdkVersion 21
        minSdkVersion 25
        targetSdkVersion 31

        renderscriptTargetApi 21
@@ -52,6 +53,7 @@ dependencies {
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation "androidx.constraintlayout:constraintlayout:2.1.3"
    implementation "org.greenrobot:eventbus:3.3.1"
    implementation 'androidx.core:core-ktx:1.8.0'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'

    // appcompat version must be 1.4.0 or later to satisfy emoji policy!
+91 −0
Original line number Diff line number Diff line
package net.sourceforge.opencamera.camera2

import android.graphics.ImageFormat
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraManager
import android.hardware.camera2.CameraMetadata
import android.os.Build
import android.util.Size
import net.sourceforge.opencamera.camera2.model.Camera2ApiProperties
import net.sourceforge.opencamera.camera2.model.CameraModel
import net.sourceforge.opencamera.camera2.model.DerivedProperties
import java.util.function.Consumer

class CameraFinder(cameraManager: CameraManager) :
    CameraFinderAbstract<ArrayList<CameraModel>>(cameraManager) {
    init {
        cameraModels = ArrayList()
    }

    public override fun createModels() {
        validCameraIds.forEach(Consumer { cameraModels.add(CameraModel(it.toInt())) })
        cameraModels.forEach(Consumer {
            it.camera2ApiProperties = findProperties(it.id, getCameraCharacteristics(it.id)!!)
        })
        cameraModels.forEach(Consumer {
            it.derivedProperties = deriveProperties(it.id, it.camera2ApiProperties)
        })
    }

    public override fun findProperties(
        cameraId: Int, characteristics: CameraCharacteristics): Camera2ApiProperties {
        return Camera2ApiProperties(cameraId).apply {
            facing = characteristics.get(CameraCharacteristics.LENS_FACING)!!
            focalLength =
                characteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS)!![0]
            aperture =
                characteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES)!![0]
            aeModes = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES)!!
            isFlashSupported = characteristics.get(
                CameraCharacteristics.FLASH_INFO_AVAILABLE)!!
            val configMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
            if (configMap?.getOutputSizes(ImageFormat.RAW_SENSOR) != null) {
                rawSensorSizes = configMap.getOutputSizes(ImageFormat.RAW_SENSOR)
            }
            sensorSize = characteristics.get(
                CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE)!!
            pixelArraySize = characteristics.get(
                CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE)!!
            supportedHardwareLevel = characteristics.get(
                CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)!!
            supportedHardwareLevelString = reflectionProvider.getResultFieldName(
                CameraMetadata::class.java,
                "INFO_SUPPORTED_HARDWARE_LEVEL_",
                supportedHardwareLevel
            )
            physicalIds = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                characteristics.physicalCameraIds
            } else {
                setOf()
            }
        }
    }

    public override fun deriveProperties(
        cameraId: Int,
        camera2ApiProperties: Camera2ApiProperties
    ): DerivedProperties {
        return DerivedProperties(cameraId).apply {
            facing = reflectionProvider.getResultFieldName(
                CameraMetadata::class.java,
                "LENS_FACING_",
                camera2ApiProperties.facing
            )
            isLogical = camera2ApiProperties.physicalIds.isNotEmpty()
            angleOfView = CameraUtil.calculateAngleOfView(
                camera2ApiProperties.focalLength,
                camera2ApiProperties.sensorSize,
                camera2ApiProperties.pixelArraySize
            )
            pixelSize = CameraUtil.calculatePixelSize(
                camera2ApiProperties.pixelArraySize.width,
                camera2ApiProperties.sensorSize.width
            )
            mm35FocalLength =
                CameraUtil.calculate35mmeqv(
                    camera2ApiProperties.focalLength,
                    camera2ApiProperties.sensorSize
                )
        }
    }
}
+68 −0
Original line number Diff line number Diff line
package net.sourceforge.opencamera.camera2

import android.hardware.camera2.CameraAccessException
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraManager
import net.sourceforge.opencamera.camera2.model.Camera2ApiProperties
import net.sourceforge.opencamera.camera2.model.CameraModel
import net.sourceforge.opencamera.camera2.model.DerivedProperties
import java.util.*
import java.util.stream.Collectors

abstract class CameraFinderAbstract<T : Iterable<CameraModel>>(
    private val cameraManager: CameraManager
) : CameraIDs.Finder<T> {
    protected val validCameraIds: MutableList<String> = ArrayList()
    protected val reflectionProvider = ReflectionProvider()
    override lateinit var cameraModels: T
        protected set

    override fun init() {
        scanCameras(cameraManager)
        createModels()
    }

    protected abstract fun createModels()
    protected abstract fun findProperties(
        cameraId: Int,
        characteristics: CameraCharacteristics
    ): Camera2ApiProperties

    protected abstract fun deriveProperties(
        cameraId: Int,
        camera2ApiProperties: Camera2ApiProperties
    ): DerivedProperties

    private fun scanCameras(cameraManager: CameraManager) {
        for (id in 0..511) {
            try {
                cameraManager.getCameraCharacteristics(id.toString())
                validCameraIds.add(id.toString())
            } catch (ignored: IllegalArgumentException) {
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    override fun getCameraCharacteristics(cameraId: Int): CameraCharacteristics? {
        try {
            return cameraManager.getCameraCharacteristics(cameraId.toString())
        } catch (e: CameraAccessException) {
            e.printStackTrace()
        }
        return null
    }

    override val apiCameraIdList: List<String>
        get() {
            try {
                return Arrays.stream(cameraManager.cameraIdList).collect(Collectors.toList())
            } catch (e: CameraAccessException) {
                e.printStackTrace()
            }
            return ArrayList()
        }
    override val allCameraIdList: List<String>
        get() = validCameraIds
}
+19 −0
Original line number Diff line number Diff line
package net.sourceforge.opencamera.camera2

import android.hardware.camera2.CameraCharacteristics
import net.sourceforge.opencamera.camera2.model.CameraModel

interface CameraIDs {
    interface Finder<T : Iterable<CameraModel>> {
        fun init()
        fun getCameraCharacteristics(cameraId: Int): CameraCharacteristics?
        val cameraModels: T
        val apiCameraIdList: List<String>
        val allCameraIdList: List<String>
    }

    interface Identifier<T : Iterable<CameraModel>> {
        fun init()
        fun identifyCamera(cameraModels: T)
    }
}
+104 −0
Original line number Diff line number Diff line
package net.sourceforge.opencamera.camera2

import android.hardware.camera2.CameraCharacteristics
import net.sourceforge.opencamera.camera2.model.Camera2ApiProperties
import net.sourceforge.opencamera.camera2.model.CameraModel
import net.sourceforge.opencamera.camera2.model.CameraType
import java.util.TreeSet
import java.util.function.Consumer
import kotlin.Comparator
import kotlin.collections.ArrayList

class CameraIdentifier(cameraModels: ArrayList<CameraModel>) :
    CameraIdentifierAbstract<ArrayList<CameraModel>>(cameraModels) {
    private val frontCameraModels = ArrayList<CameraModel>()
    private val backCameraModels = ArrayList<CameraModel>()
    private val widerThanMain = TreeSet(SORT_BY_ANGLE_OF_VIEW)
    private val narrowerThanMain = ArrayList<CameraModel>()
    private val propertiesArrayList = ArrayList<Camera2ApiProperties>()
    override fun init() {
        cameraModels.forEach(Consumer {
            propertiesArrayList.add(it.camera2ApiProperties)
        })
        frontOrBack(cameraModels)
        identifyCamera(frontCameraModels)
        identifyCamera(backCameraModels)
    }

    private fun frontOrBack(cameraModels: Collection<CameraModel>) {
        for (model in cameraModels) {
            if (model.camera2ApiProperties.facing == CameraCharacteristics.LENS_FACING_BACK) {
                backCameraModels.add(model)
            }
            if (model.camera2ApiProperties.facing == CameraCharacteristics.LENS_FACING_FRONT) {
                frontCameraModels.add(model)
            }
        }
    }

    override fun identifyCamera(cameraModels: ArrayList<CameraModel>) {
        if (cameraModels.isNotEmpty()) {
            val main = cameraModels[0]
            main.cameraType = CameraType.MAIN
            main.zoomFactor = 1f
            cameraModels.removeAt(0)

            //Determine whether camera is logical
            cameraModels.forEach(Consumer { model: CameraModel ->
                if (model.derivedProperties.isLogical || getBit(6, model.id)) {
                    model.cameraType = CameraType.LOGICAL
                }
                propertiesArrayList.forEach(Consumer {
                    if (model.id != it.id && model.camera2ApiProperties == it) {
                        model.cameraType = CameraType.LOGICAL
                    }
                })
            })
            cameraModels.removeIf { it.isTypeSet }
            cameraModels.sortWith(SORT_BY_ANGLE_OF_VIEW)
            cameraModels.forEach(Consumer {
                val zoom =
                    it.derivedProperties.mm35FocalLength / main.derivedProperties.mm35FocalLength
                it.zoomFactor = zoom

                //Determine whether camera is Depth or Other
                it.cameraType = CameraType.OTHER
                if (!it.camera2ApiProperties.isFlashSupported) {
                    it.cameraType = CameraType.DEPTH
                } else {
                    if (it.derivedProperties.angleOfView > main.derivedProperties.angleOfView) {
                        widerThanMain.add(it)
                    } else {
                        narrowerThanMain.add(it)
                    }
                }
            })

            //Determine whether camera is Ultrawide or Macro
            widerThanMain.forEach(Consumer {
                it.cameraType = if (
                    it.derivedProperties.angleOfView ==
                    widerThanMain.last().derivedProperties.angleOfView
                ) {
                    CameraType.ULTRAWIDE
                } else {
                    CameraType.MACRO
                }
            })

            // Determine whether camera is Tele
            narrowerThanMain.forEach(Consumer { cameraModel: CameraModel ->
                cameraModel.cameraType = CameraType.TELE
            })
        }
    }

    private fun getBit(num: Int, `val`: Int): Boolean {
        return `val` shr num - 1 and 1 == 1
    }

    companion object {
        private val SORT_BY_ANGLE_OF_VIEW =
            Comparator.comparingDouble { cameraModel: CameraModel -> cameraModel.derivedProperties.angleOfView }
    }
}
Loading