From fa1119a3b015b4de048fc8980f15be57cc0821f5 Mon Sep 17 00:00:00 2001 From: David Jia Date: Thu, 29 Aug 2024 16:45:16 -0700 Subject: [PATCH 01/12] Save Camera Properties to external file --- .../core/camera/CameraUseCase.kt | 6 +- .../core/camera/CameraXCameraUseCase.kt | 135 ++++++++++++++++-- .../core/camera/test/FakeCameraUseCase.kt | 3 +- .../feature/preview/PreviewViewModel.kt | 3 +- 4 files changed, 131 insertions(+), 16 deletions(-) diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraUseCase.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraUseCase.kt index 26e72b81..199c50ce 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraUseCase.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraUseCase.kt @@ -41,7 +41,11 @@ interface CameraUseCase { * * @return list of available lenses. */ - suspend fun initialize(cameraAppSettings: CameraAppSettings, useCaseMode: UseCaseMode) + suspend fun initialize( + cameraAppSettings: CameraAppSettings, + useCaseMode: UseCaseMode, + isDebugMode: Boolean = false + ) /** * Starts the camera. diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt index 3db618dd..dab44c41 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt @@ -19,20 +19,32 @@ import android.Manifest import android.app.Application import android.content.ContentResolver import android.content.ContentValues +import android.content.Context import android.content.pm.PackageManager import android.hardware.camera2.CameraCaptureSession import android.hardware.camera2.CameraCharacteristics +import android.hardware.camera2.CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE +import android.hardware.camera2.CameraCharacteristics.LENS_DISTORTION +import android.hardware.camera2.CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS +import android.hardware.camera2.CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE +import android.hardware.camera2.CameraCharacteristics.LENS_INTRINSIC_CALIBRATION +import android.hardware.camera2.CameraCharacteristics.LENS_POSE_ROTATION +import android.hardware.camera2.CameraCharacteristics.LENS_POSE_TRANSLATION +import android.hardware.camera2.CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES +import android.hardware.camera2.CameraManager import android.hardware.camera2.CaptureRequest import android.hardware.camera2.CaptureResult import android.hardware.camera2.TotalCaptureResult import android.net.Uri import android.os.Build import android.os.Environment +import android.os.Environment.DIRECTORY_DOCUMENTS import android.os.SystemClock import android.provider.MediaStore import android.util.Log import android.util.Range import androidx.annotation.OptIn +import androidx.annotation.RequiresApi import androidx.camera.camera2.interop.Camera2CameraInfo import androidx.camera.camera2.interop.Camera2Interop import androidx.camera.camera2.interop.ExperimentalCamera2Interop @@ -43,7 +55,6 @@ import androidx.camera.core.CameraControl import androidx.camera.core.CameraEffect import androidx.camera.core.CameraInfo import androidx.camera.core.CameraSelector -import androidx.camera.core.DynamicRange as CXDynamicRange import androidx.camera.core.ExperimentalImageCaptureOutputFormat import androidx.camera.core.FocusMeteringAction import androidx.camera.core.ImageCapture @@ -90,17 +101,6 @@ import com.google.jetpackcamera.settings.model.Stabilization import com.google.jetpackcamera.settings.model.SupportedStabilizationMode import com.google.jetpackcamera.settings.model.SystemConstraints import dagger.hilt.android.scopes.ViewModelScoped -import java.io.File -import java.io.FileNotFoundException -import java.text.SimpleDateFormat -import java.util.Calendar -import java.util.Date -import java.util.Locale -import java.util.concurrent.Executor -import javax.inject.Inject -import kotlin.coroutines.ContinuationInterceptor -import kotlin.math.abs -import kotlin.properties.Delegates import kotlinx.atomicfu.atomic import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope @@ -124,6 +124,22 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import org.json.JSONArray +import org.json.JSONObject +import java.io.File +import java.io.FileNotFoundException +import java.io.FileOutputStream +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Date +import java.util.Locale +import java.util.concurrent.Executor +import javax.inject.Inject +import kotlin.coroutines.ContinuationInterceptor +import kotlin.math.abs +import kotlin.properties.Delegates +import androidx.camera.core.DynamicRange as CXDynamicRange + private const val TAG = "CameraXCameraUseCase" const val TARGET_FPS_AUTO = 0 @@ -170,6 +186,8 @@ constructor( if (!physicalCameraId.equals(this.physicalCameraId) || logicalCameraId != this.logicalCameraId ) { + this.physicalCameraId = physicalCameraId + this.logicalCameraId = logicalCameraId _currentCameraState.update { old -> old.copy( debugInfo = DebugInfo(logicalCameraId, physicalCameraId) @@ -197,6 +215,87 @@ constructor( imageCaptureExtender.setSessionCaptureCallback(captureCallback) } + @RequiresApi(Build.VERSION_CODES.P) + private fun getAllCamerasPropertiesJSONArray(): JSONArray { + val cameraManager = + this.application.baseContext.getSystemService(Context.CAMERA_SERVICE) as CameraManager + val result = JSONArray() + for (logicalCameraId in cameraManager.cameraIdList) { + val logicalCameraData = JSONObject() + logicalCameraData.put( + "logical-$logicalCameraId", + getCameraPropertiesJSONObject(logicalCameraId, cameraManager) + ) + for (physicalCameraId in + cameraManager.getCameraCharacteristics(logicalCameraId).physicalCameraIds) { + logicalCameraData.put( + "physical-$physicalCameraId", + getCameraPropertiesJSONObject(physicalCameraId, cameraManager) + ) + } + result.put(logicalCameraData) + } + return result + } + + private fun getCameraPropertiesJSONObject( + cameraId: String, + cameraManager: CameraManager + ): JSONObject { + val cameraCharacteristics = + cameraManager.getCameraCharacteristics(cameraId) + val jsonObject = JSONObject() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + cameraCharacteristics.get(LENS_POSE_ROTATION) + ?.let { jsonObject.put(LENS_POSE_ROTATION.name, it) } + cameraCharacteristics.get(LENS_POSE_TRANSLATION) + ?.let { jsonObject.put(LENS_POSE_TRANSLATION.name, it) } + cameraCharacteristics.get(LENS_INTRINSIC_CALIBRATION) + ?.let { jsonObject.put(LENS_INTRINSIC_CALIBRATION.name, it) } + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + cameraCharacteristics.get(LENS_DISTORTION) + ?.let { jsonObject.put(LENS_DISTORTION.name, it) } + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + cameraCharacteristics.get(CONTROL_ZOOM_RATIO_RANGE) + ?.let { jsonObject.put(CONTROL_ZOOM_RATIO_RANGE.name, it) } + } + cameraCharacteristics.get(LENS_INFO_AVAILABLE_FOCAL_LENGTHS) + ?.let { jsonObject.put(LENS_INFO_AVAILABLE_FOCAL_LENGTHS.name, it) } + cameraCharacteristics.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE) + ?.let { jsonObject.put(LENS_INFO_MINIMUM_FOCUS_DISTANCE.name, it) } + cameraCharacteristics.get(REQUEST_AVAILABLE_CAPABILITIES) + ?.let { jsonObject.put(REQUEST_AVAILABLE_CAPABILITIES.name, it) } + + return jsonObject + } + + private fun writeFileExternalStorage(file: File, textToWrite: String) { + //Checking the availability state of the External Storage. + val state = Environment.getExternalStorageState() + if (Environment.MEDIA_MOUNTED != state) { + //If it isn't mounted - we can't write into it. + + return + } + + //This point and below is responsible for the write operation + var outputStream: FileOutputStream? = null + try { + file.createNewFile() + //second argument of FileOutputStream constructor indicates whether + //to append or create new file if one exists + outputStream = FileOutputStream(file, true) + + outputStream.write(textToWrite.toByteArray()) + outputStream.flush() + outputStream.close() + } catch (e: java.lang.Exception) { + e.printStackTrace() + } + } + private var imageCaptureUseCase: ImageCapture? = null private lateinit var captureMode: CaptureMode @@ -213,7 +312,8 @@ constructor( override suspend fun initialize( cameraAppSettings: CameraAppSettings, - useCaseMode: CameraUseCase.UseCaseMode + useCaseMode: CameraUseCase.UseCaseMode, + isDebugMode: Boolean ) { this.useCaseMode = useCaseMode cameraProvider = ProcessCameraProvider.awaitInstance(application) @@ -284,6 +384,15 @@ constructor( .tryApplyImageFormatConstraints() .tryApplyFrameRateConstraints() .tryApplyStabilizationConstraints() + if (isDebugMode && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + val cameraProperties = getAllCamerasPropertiesJSONArray().toString() + val file = File( + Environment.getExternalStoragePublicDirectory(DIRECTORY_DOCUMENTS), + "JCACameraProperties" + ) + writeFileExternalStorage(file, cameraProperties) + Log.d(TAG, "JCACameraProperties written to ${file.path}. \n" + "$cameraProperties") + } } /** diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/test/FakeCameraUseCase.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/test/FakeCameraUseCase.kt index e581352f..1a28c554 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/test/FakeCameraUseCase.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/test/FakeCameraUseCase.kt @@ -67,7 +67,8 @@ class FakeCameraUseCase( override suspend fun initialize( cameraAppSettings: CameraAppSettings, - useCaseMode: CameraUseCase.UseCaseMode + useCaseMode: CameraUseCase.UseCaseMode, + isDebugMode: Boolean ) { initialized = true } diff --git a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt index 70f96d62..58ef3ab0 100644 --- a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt +++ b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt @@ -108,7 +108,8 @@ class PreviewViewModel @AssistedInject constructor( private var initializationDeferred: Deferred = viewModelScope.async { cameraUseCase.initialize( cameraAppSettings = settingsRepository.defaultCameraAppSettings.first(), - previewMode.toUseCaseMode() + previewMode.toUseCaseMode(), + isDebugMode ) } From 97eb74a8b104a1498c6a5cda17855f9196bb1070 Mon Sep 17 00:00:00 2001 From: David Jia Date: Wed, 4 Sep 2024 14:29:55 -0700 Subject: [PATCH 02/12] address comments --- .../core/camera/CameraXCameraUseCase.kt | 141 ++++-------------- .../core/camera/DebugCameraInfoUtil.kt | 115 ++++++++++++++ 2 files changed, 143 insertions(+), 113 deletions(-) create mode 100644 core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt index dab44c41..c7fee988 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt @@ -23,14 +23,6 @@ import android.content.Context import android.content.pm.PackageManager import android.hardware.camera2.CameraCaptureSession import android.hardware.camera2.CameraCharacteristics -import android.hardware.camera2.CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE -import android.hardware.camera2.CameraCharacteristics.LENS_DISTORTION -import android.hardware.camera2.CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS -import android.hardware.camera2.CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE -import android.hardware.camera2.CameraCharacteristics.LENS_INTRINSIC_CALIBRATION -import android.hardware.camera2.CameraCharacteristics.LENS_POSE_ROTATION -import android.hardware.camera2.CameraCharacteristics.LENS_POSE_TRANSLATION -import android.hardware.camera2.CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES import android.hardware.camera2.CameraManager import android.hardware.camera2.CaptureRequest import android.hardware.camera2.CaptureResult @@ -44,7 +36,6 @@ import android.provider.MediaStore import android.util.Log import android.util.Range import androidx.annotation.OptIn -import androidx.annotation.RequiresApi import androidx.camera.camera2.interop.Camera2CameraInfo import androidx.camera.camera2.interop.Camera2Interop import androidx.camera.camera2.interop.ExperimentalCamera2Interop @@ -55,6 +46,7 @@ import androidx.camera.core.CameraControl import androidx.camera.core.CameraEffect import androidx.camera.core.CameraInfo import androidx.camera.core.CameraSelector +import androidx.camera.core.DynamicRange as CXDynamicRange import androidx.camera.core.ExperimentalImageCaptureOutputFormat import androidx.camera.core.FocusMeteringAction import androidx.camera.core.ImageCapture @@ -85,6 +77,8 @@ import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat.checkSelfPermission import androidx.lifecycle.asFlow import com.google.jetpackcamera.core.camera.CameraUseCase.ScreenFlashEvent.Type +import com.google.jetpackcamera.core.camera.DebugCameraInfoUtil.getAllCamerasPropertiesJSONArray +import com.google.jetpackcamera.core.camera.DebugCameraInfoUtil.writeFileExternalStorage import com.google.jetpackcamera.core.camera.effects.SingleSurfaceForcingEffect import com.google.jetpackcamera.settings.SettableConstraintsRepository import com.google.jetpackcamera.settings.model.AspectRatio @@ -101,10 +95,22 @@ import com.google.jetpackcamera.settings.model.Stabilization import com.google.jetpackcamera.settings.model.SupportedStabilizationMode import com.google.jetpackcamera.settings.model.SystemConstraints import dagger.hilt.android.scopes.ViewModelScoped +import java.io.File +import java.io.FileNotFoundException +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Date +import java.util.Locale +import java.util.concurrent.Executor +import javax.inject.Inject +import kotlin.coroutines.ContinuationInterceptor +import kotlin.math.abs +import kotlin.properties.Delegates import kotlinx.atomicfu.atomic import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.asExecutor import kotlinx.coroutines.channels.Channel @@ -124,22 +130,7 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import org.json.JSONArray -import org.json.JSONObject -import java.io.File -import java.io.FileNotFoundException -import java.io.FileOutputStream -import java.text.SimpleDateFormat -import java.util.Calendar -import java.util.Date -import java.util.Locale -import java.util.concurrent.Executor -import javax.inject.Inject -import kotlin.coroutines.ContinuationInterceptor -import kotlin.math.abs -import kotlin.properties.Delegates -import androidx.camera.core.DynamicRange as CXDynamicRange - +import kotlinx.coroutines.withContext private const val TAG = "CameraXCameraUseCase" const val TARGET_FPS_AUTO = 0 @@ -215,87 +206,6 @@ constructor( imageCaptureExtender.setSessionCaptureCallback(captureCallback) } - @RequiresApi(Build.VERSION_CODES.P) - private fun getAllCamerasPropertiesJSONArray(): JSONArray { - val cameraManager = - this.application.baseContext.getSystemService(Context.CAMERA_SERVICE) as CameraManager - val result = JSONArray() - for (logicalCameraId in cameraManager.cameraIdList) { - val logicalCameraData = JSONObject() - logicalCameraData.put( - "logical-$logicalCameraId", - getCameraPropertiesJSONObject(logicalCameraId, cameraManager) - ) - for (physicalCameraId in - cameraManager.getCameraCharacteristics(logicalCameraId).physicalCameraIds) { - logicalCameraData.put( - "physical-$physicalCameraId", - getCameraPropertiesJSONObject(physicalCameraId, cameraManager) - ) - } - result.put(logicalCameraData) - } - return result - } - - private fun getCameraPropertiesJSONObject( - cameraId: String, - cameraManager: CameraManager - ): JSONObject { - val cameraCharacteristics = - cameraManager.getCameraCharacteristics(cameraId) - val jsonObject = JSONObject() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - cameraCharacteristics.get(LENS_POSE_ROTATION) - ?.let { jsonObject.put(LENS_POSE_ROTATION.name, it) } - cameraCharacteristics.get(LENS_POSE_TRANSLATION) - ?.let { jsonObject.put(LENS_POSE_TRANSLATION.name, it) } - cameraCharacteristics.get(LENS_INTRINSIC_CALIBRATION) - ?.let { jsonObject.put(LENS_INTRINSIC_CALIBRATION.name, it) } - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - cameraCharacteristics.get(LENS_DISTORTION) - ?.let { jsonObject.put(LENS_DISTORTION.name, it) } - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - cameraCharacteristics.get(CONTROL_ZOOM_RATIO_RANGE) - ?.let { jsonObject.put(CONTROL_ZOOM_RATIO_RANGE.name, it) } - } - cameraCharacteristics.get(LENS_INFO_AVAILABLE_FOCAL_LENGTHS) - ?.let { jsonObject.put(LENS_INFO_AVAILABLE_FOCAL_LENGTHS.name, it) } - cameraCharacteristics.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE) - ?.let { jsonObject.put(LENS_INFO_MINIMUM_FOCUS_DISTANCE.name, it) } - cameraCharacteristics.get(REQUEST_AVAILABLE_CAPABILITIES) - ?.let { jsonObject.put(REQUEST_AVAILABLE_CAPABILITIES.name, it) } - - return jsonObject - } - - private fun writeFileExternalStorage(file: File, textToWrite: String) { - //Checking the availability state of the External Storage. - val state = Environment.getExternalStorageState() - if (Environment.MEDIA_MOUNTED != state) { - //If it isn't mounted - we can't write into it. - - return - } - - //This point and below is responsible for the write operation - var outputStream: FileOutputStream? = null - try { - file.createNewFile() - //second argument of FileOutputStream constructor indicates whether - //to append or create new file if one exists - outputStream = FileOutputStream(file, true) - - outputStream.write(textToWrite.toByteArray()) - outputStream.flush() - outputStream.close() - } catch (e: java.lang.Exception) { - e.printStackTrace() - } - } - private var imageCaptureUseCase: ImageCapture? = null private lateinit var captureMode: CaptureMode @@ -385,13 +295,18 @@ constructor( .tryApplyFrameRateConstraints() .tryApplyStabilizationConstraints() if (isDebugMode && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - val cameraProperties = getAllCamerasPropertiesJSONArray().toString() - val file = File( - Environment.getExternalStoragePublicDirectory(DIRECTORY_DOCUMENTS), - "JCACameraProperties" - ) - writeFileExternalStorage(file, cameraProperties) - Log.d(TAG, "JCACameraProperties written to ${file.path}. \n" + "$cameraProperties") + withContext(Dispatchers.IO) { + val cameraManager = application.baseContext.getSystemService(Context.CAMERA_SERVICE) + as CameraManager + val cameraProperties = getAllCamerasPropertiesJSONArray(cameraManager).toString() + val file = File( + Environment.getExternalStoragePublicDirectory(DIRECTORY_DOCUMENTS), + "JCACameraProperties" + ) + writeFileExternalStorage(file, cameraProperties) + Log.d(TAG, "JCACameraProperties written to ${file.path}. \n$cameraProperties") + } + } } diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt new file mode 100644 index 00000000..5b11c317 --- /dev/null +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.jetpackcamera.core.camera + +import android.hardware.camera2.CameraCharacteristics +import android.hardware.camera2.CameraManager +import android.os.Build +import android.os.Environment +import androidx.annotation.RequiresApi +import org.json.JSONArray +import org.json.JSONObject +import java.io.File +import java.io.FileOutputStream + +private const val TAG = "DebugCameraInfoUtil" +object DebugCameraInfoUtil { + @RequiresApi(Build.VERSION_CODES.P) + fun getAllCamerasPropertiesJSONArray(cameraManager: CameraManager): JSONArray { + val result = JSONArray() + for (logicalCameraId in cameraManager.cameraIdList) { + val logicalCameraData = JSONObject() + logicalCameraData.put( + "logical-$logicalCameraId", + getCameraPropertiesJSONObject(logicalCameraId, cameraManager) + ) + for (physicalCameraId in + cameraManager.getCameraCharacteristics(logicalCameraId).physicalCameraIds) { + logicalCameraData.put( + "physical-$physicalCameraId", + getCameraPropertiesJSONObject(physicalCameraId, cameraManager) + ) + } + result.put(logicalCameraData) + } + return result + } + + private fun getCameraPropertiesJSONObject( + cameraId: String, + cameraManager: CameraManager + ): JSONObject { + val cameraCharacteristics = + cameraManager.getCameraCharacteristics(cameraId) + val jsonObject = JSONObject() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + cameraCharacteristics.get(CameraCharacteristics.LENS_POSE_ROTATION) + ?.let { jsonObject.put(CameraCharacteristics.LENS_POSE_ROTATION.name, it) } + cameraCharacteristics.get(CameraCharacteristics.LENS_POSE_TRANSLATION) + ?.let { jsonObject.put(CameraCharacteristics.LENS_POSE_TRANSLATION.name, it) } + cameraCharacteristics.get(CameraCharacteristics.LENS_INTRINSIC_CALIBRATION) + ?.let { jsonObject.put(CameraCharacteristics.LENS_INTRINSIC_CALIBRATION.name, it) } + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + cameraCharacteristics.get(CameraCharacteristics.LENS_DISTORTION) + ?.let { jsonObject.put(CameraCharacteristics.LENS_DISTORTION.name, it) } + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + cameraCharacteristics.get(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE) + ?.let { jsonObject.put(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE.name, it) } + } + cameraCharacteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS) + ?.let { + jsonObject.put( + CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS.name, + it + ) + } + cameraCharacteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE) + ?.let { + jsonObject.put( + CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE.name, + it + ) + } + cameraCharacteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES) + ?.let { jsonObject.put(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES.name, it) } + + return jsonObject + } + + fun writeFileExternalStorage(file: File, textToWrite: String) { + //Checking the availability state of the External Storage. + val state = Environment.getExternalStorageState() + if (Environment.MEDIA_MOUNTED != state) { + //If it isn't mounted - we can't write into it. + return + } + + //This point and below is responsible for the write operation + var outputStream: FileOutputStream? = null + file.createNewFile() + //second argument of FileOutputStream constructor indicates whether + //to append or create new file if one exists + outputStream = FileOutputStream(file, true) + + FileOutputStream(file).use { outputStream -> + outputStream.write(textToWrite.toByteArray()) + } + outputStream.close() + } +} From a91bc5c15ee81a2706e4499d2974fa09443dfeaa Mon Sep 17 00:00:00 2001 From: David Jia Date: Wed, 4 Sep 2024 14:44:51 -0700 Subject: [PATCH 03/12] update --- .../java/com/google/jetpackcamera/MainActivity.kt | 2 +- .../jetpackcamera/core/camera/CameraXCameraUseCase.kt | 3 +-- .../jetpackcamera/core/camera/DebugCameraInfoUtil.kt | 11 ++++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/google/jetpackcamera/MainActivity.kt b/app/src/main/java/com/google/jetpackcamera/MainActivity.kt index cb7f572a..def60aa3 100644 --- a/app/src/main/java/com/google/jetpackcamera/MainActivity.kt +++ b/app/src/main/java/com/google/jetpackcamera/MainActivity.kt @@ -163,7 +163,7 @@ class MainActivity : ComponentActivity() { } private val isDebugMode: Boolean - get() = intent?.getBooleanExtra(KEY_DEBUG_MODE, false) ?: false + get() = true private fun getStandardMode(): PreviewMode.StandardMode { return PreviewMode.StandardMode { event -> diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt index c7fee988..478fa9bd 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt @@ -297,7 +297,7 @@ constructor( if (isDebugMode && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { withContext(Dispatchers.IO) { val cameraManager = application.baseContext.getSystemService(Context.CAMERA_SERVICE) - as CameraManager + as CameraManager val cameraProperties = getAllCamerasPropertiesJSONArray(cameraManager).toString() val file = File( Environment.getExternalStoragePublicDirectory(DIRECTORY_DOCUMENTS), @@ -306,7 +306,6 @@ constructor( writeFileExternalStorage(file, cameraProperties) Log.d(TAG, "JCACameraProperties written to ${file.path}. \n$cameraProperties") } - } } diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt index 5b11c317..d363561d 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.google.jetpackcamera.core.camera import android.hardware.camera2.CameraCharacteristics @@ -21,10 +20,10 @@ import android.hardware.camera2.CameraManager import android.os.Build import android.os.Environment import androidx.annotation.RequiresApi -import org.json.JSONArray -import org.json.JSONObject import java.io.File import java.io.FileOutputStream +import org.json.JSONArray +import org.json.JSONObject private const val TAG = "DebugCameraInfoUtil" object DebugCameraInfoUtil { @@ -37,8 +36,10 @@ object DebugCameraInfoUtil { "logical-$logicalCameraId", getCameraPropertiesJSONObject(logicalCameraId, cameraManager) ) - for (physicalCameraId in - cameraManager.getCameraCharacteristics(logicalCameraId).physicalCameraIds) { + for ( + physicalCameraId in + cameraManager.getCameraCharacteristics(logicalCameraId).physicalCameraIds + ) { logicalCameraData.put( "physical-$physicalCameraId", getCameraPropertiesJSONObject(physicalCameraId, cameraManager) From b46f13f2e77bb62309ae4e1e92a61ed1b3db5963 Mon Sep 17 00:00:00 2001 From: David Jia Date: Wed, 4 Sep 2024 15:35:41 -0700 Subject: [PATCH 04/12] Update DebugCameraInfoUtil.kt --- .../jetpackcamera/core/camera/DebugCameraInfoUtil.kt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt index d363561d..526ce145 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt @@ -94,18 +94,15 @@ object DebugCameraInfoUtil { } fun writeFileExternalStorage(file: File, textToWrite: String) { - //Checking the availability state of the External Storage. + // Checking the availability state of the External Storage. val state = Environment.getExternalStorageState() if (Environment.MEDIA_MOUNTED != state) { - //If it isn't mounted - we can't write into it. + // If it isn't mounted - we can't write into it. return } - //This point and below is responsible for the write operation var outputStream: FileOutputStream? = null file.createNewFile() - //second argument of FileOutputStream constructor indicates whether - //to append or create new file if one exists outputStream = FileOutputStream(file, true) FileOutputStream(file).use { outputStream -> From d4bfdaf6c93c4e00cc3620761c9bed68b47e3a7a Mon Sep 17 00:00:00 2001 From: David Jia Date: Mon, 9 Sep 2024 13:16:31 -0700 Subject: [PATCH 05/12] address comments --- .../com/google/jetpackcamera/MainActivity.kt | 2 +- .../core/camera/CameraXCameraUseCase.kt | 14 +++--- .../core/camera/DebugCameraInfoUtil.kt | 47 ++++++++++--------- .../jetpackcamera/core/common/CommonModule.kt | 6 +++ 4 files changed, 37 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/com/google/jetpackcamera/MainActivity.kt b/app/src/main/java/com/google/jetpackcamera/MainActivity.kt index def60aa3..cb7f572a 100644 --- a/app/src/main/java/com/google/jetpackcamera/MainActivity.kt +++ b/app/src/main/java/com/google/jetpackcamera/MainActivity.kt @@ -163,7 +163,7 @@ class MainActivity : ComponentActivity() { } private val isDebugMode: Boolean - get() = true + get() = intent?.getBooleanExtra(KEY_DEBUG_MODE, false) ?: false private fun getStandardMode(): PreviewMode.StandardMode { return PreviewMode.StandardMode { event -> diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt index 478fa9bd..63416f4d 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt @@ -19,11 +19,9 @@ import android.Manifest import android.app.Application import android.content.ContentResolver import android.content.ContentValues -import android.content.Context import android.content.pm.PackageManager import android.hardware.camera2.CameraCaptureSession import android.hardware.camera2.CameraCharacteristics -import android.hardware.camera2.CameraManager import android.hardware.camera2.CaptureRequest import android.hardware.camera2.CaptureResult import android.hardware.camera2.TotalCaptureResult @@ -110,7 +108,6 @@ import kotlinx.atomicfu.atomic import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.asExecutor import kotlinx.coroutines.channels.Channel @@ -131,6 +128,7 @@ import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import javax.inject.Named private const val TAG = "CameraXCameraUseCase" const val TARGET_FPS_AUTO = 0 @@ -147,7 +145,8 @@ class CameraXCameraUseCase constructor( private val application: Application, private val coroutineScope: CoroutineScope, - private val defaultDispatcher: CoroutineDispatcher, + @Named("defaultDispatcher") private val defaultDispatcher: CoroutineDispatcher, + @Named("iODispatcher")private val iODispatcher: CoroutineDispatcher, private val constraintsRepository: SettableConstraintsRepository ) : CameraUseCase { private lateinit var cameraProvider: ProcessCameraProvider @@ -295,10 +294,9 @@ constructor( .tryApplyFrameRateConstraints() .tryApplyStabilizationConstraints() if (isDebugMode && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - withContext(Dispatchers.IO) { - val cameraManager = application.baseContext.getSystemService(Context.CAMERA_SERVICE) - as CameraManager - val cameraProperties = getAllCamerasPropertiesJSONArray(cameraManager).toString() + withContext(iODispatcher) { + val cameraProperties = + getAllCamerasPropertiesJSONArray(cameraProvider.availableCameraInfos).toString() val file = File( Environment.getExternalStoragePublicDirectory(DIRECTORY_DOCUMENTS), "JCACameraProperties" diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt index 526ce145..dcda6c0b 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt @@ -16,10 +16,13 @@ package com.google.jetpackcamera.core.camera import android.hardware.camera2.CameraCharacteristics -import android.hardware.camera2.CameraManager import android.os.Build import android.os.Environment +import androidx.annotation.OptIn import androidx.annotation.RequiresApi +import androidx.camera.camera2.interop.Camera2CameraInfo +import androidx.camera.camera2.interop.ExperimentalCamera2Interop +import androidx.camera.core.CameraInfo import java.io.File import java.io.FileOutputStream import org.json.JSONArray @@ -27,22 +30,24 @@ import org.json.JSONObject private const val TAG = "DebugCameraInfoUtil" object DebugCameraInfoUtil { + @OptIn(ExperimentalCamera2Interop::class) @RequiresApi(Build.VERSION_CODES.P) - fun getAllCamerasPropertiesJSONArray(cameraManager: CameraManager): JSONArray { + fun getAllCamerasPropertiesJSONArray(cameraInfos: List): JSONArray { val result = JSONArray() - for (logicalCameraId in cameraManager.cameraIdList) { + for (cameraInfo in cameraInfos) { + var camera2cameraInfo = Camera2CameraInfo.from(cameraInfo) + val logicalCameraId = camera2cameraInfo.cameraId val logicalCameraData = JSONObject() logicalCameraData.put( "logical-$logicalCameraId", - getCameraPropertiesJSONObject(logicalCameraId, cameraManager) + getCameraPropertiesJSONObject(camera2cameraInfo) ) - for ( - physicalCameraId in - cameraManager.getCameraCharacteristics(logicalCameraId).physicalCameraIds - ) { + for (cameraInfo in cameraInfo.physicalCameraInfos) { + camera2cameraInfo = Camera2CameraInfo.from(cameraInfo) + val physicalCameraId = Camera2CameraInfo.from(cameraInfo).cameraId logicalCameraData.put( "physical-$physicalCameraId", - getCameraPropertiesJSONObject(physicalCameraId, cameraManager) + getCameraPropertiesJSONObject(camera2cameraInfo) ) } result.put(logicalCameraData) @@ -50,44 +55,40 @@ object DebugCameraInfoUtil { return result } - private fun getCameraPropertiesJSONObject( - cameraId: String, - cameraManager: CameraManager - ): JSONObject { - val cameraCharacteristics = - cameraManager.getCameraCharacteristics(cameraId) + @OptIn(ExperimentalCamera2Interop::class) + private fun getCameraPropertiesJSONObject(cameraInfo: Camera2CameraInfo): JSONObject { val jsonObject = JSONObject() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - cameraCharacteristics.get(CameraCharacteristics.LENS_POSE_ROTATION) + cameraInfo.getCameraCharacteristic(CameraCharacteristics.LENS_POSE_ROTATION) ?.let { jsonObject.put(CameraCharacteristics.LENS_POSE_ROTATION.name, it) } - cameraCharacteristics.get(CameraCharacteristics.LENS_POSE_TRANSLATION) + cameraInfo.getCameraCharacteristic(CameraCharacteristics.LENS_POSE_TRANSLATION) ?.let { jsonObject.put(CameraCharacteristics.LENS_POSE_TRANSLATION.name, it) } - cameraCharacteristics.get(CameraCharacteristics.LENS_INTRINSIC_CALIBRATION) + cameraInfo.getCameraCharacteristic(CameraCharacteristics.LENS_INTRINSIC_CALIBRATION) ?.let { jsonObject.put(CameraCharacteristics.LENS_INTRINSIC_CALIBRATION.name, it) } } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - cameraCharacteristics.get(CameraCharacteristics.LENS_DISTORTION) + cameraInfo.getCameraCharacteristic(CameraCharacteristics.LENS_DISTORTION) ?.let { jsonObject.put(CameraCharacteristics.LENS_DISTORTION.name, it) } } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - cameraCharacteristics.get(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE) + cameraInfo.getCameraCharacteristic(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE) ?.let { jsonObject.put(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE.name, it) } } - cameraCharacteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS) + cameraInfo.getCameraCharacteristic(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS) ?.let { jsonObject.put( CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS.name, it ) } - cameraCharacteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE) + cameraInfo.getCameraCharacteristic(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE) ?.let { jsonObject.put( CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE.name, it ) } - cameraCharacteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES) + cameraInfo.getCameraCharacteristic(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES) ?.let { jsonObject.put(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES.name, it) } return jsonObject diff --git a/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt b/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt index 519f90fa..9ccca8bf 100644 --- a/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt +++ b/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt @@ -24,6 +24,7 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob +import javax.inject.Named /** * Dagger [Module] for Common dependencies. @@ -32,8 +33,13 @@ import kotlinx.coroutines.SupervisorJob @InstallIn(SingletonComponent::class) class CommonModule { @Provides + @Named("defaultDispatcher") fun provideDefaultDispatcher(): CoroutineDispatcher = Dispatchers.Default + @Provides + @Named("iODispatcher") + fun provideIODispatcher(): CoroutineDispatcher = Dispatchers.IO + @Singleton @Provides fun providesCoroutineScope() = CoroutineScope(SupervisorJob() + Dispatchers.Default) From 77ab2853cbb6d41c56a6a957d0c22eae621414ab Mon Sep 17 00:00:00 2001 From: David Jia Date: Mon, 9 Sep 2024 13:23:13 -0700 Subject: [PATCH 06/12] Update DebugCameraInfoUtil.kt --- .../core/camera/DebugCameraInfoUtil.kt | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt index dcda6c0b..4dd81032 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt @@ -60,15 +60,35 @@ object DebugCameraInfoUtil { val jsonObject = JSONObject() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { cameraInfo.getCameraCharacteristic(CameraCharacteristics.LENS_POSE_ROTATION) - ?.let { jsonObject.put(CameraCharacteristics.LENS_POSE_ROTATION.name, it) } + ?.let { + jsonObject.put( + CameraCharacteristics.LENS_POSE_ROTATION.name, + it.contentToString() + ) + } cameraInfo.getCameraCharacteristic(CameraCharacteristics.LENS_POSE_TRANSLATION) - ?.let { jsonObject.put(CameraCharacteristics.LENS_POSE_TRANSLATION.name, it) } + ?.let { + jsonObject.put( + CameraCharacteristics.LENS_POSE_TRANSLATION.name, + it.contentToString() + ) + } cameraInfo.getCameraCharacteristic(CameraCharacteristics.LENS_INTRINSIC_CALIBRATION) - ?.let { jsonObject.put(CameraCharacteristics.LENS_INTRINSIC_CALIBRATION.name, it) } + ?.let { + jsonObject.put( + CameraCharacteristics.LENS_INTRINSIC_CALIBRATION.name, + it.contentToString() + ) + } } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { cameraInfo.getCameraCharacteristic(CameraCharacteristics.LENS_DISTORTION) - ?.let { jsonObject.put(CameraCharacteristics.LENS_DISTORTION.name, it) } + ?.let { + jsonObject.put( + CameraCharacteristics.LENS_DISTORTION.name, + it.contentToString() + ) + } } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { cameraInfo.getCameraCharacteristic(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE) @@ -78,7 +98,7 @@ object DebugCameraInfoUtil { ?.let { jsonObject.put( CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS.name, - it + it.contentToString() ) } cameraInfo.getCameraCharacteristic(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE) @@ -89,7 +109,12 @@ object DebugCameraInfoUtil { ) } cameraInfo.getCameraCharacteristic(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES) - ?.let { jsonObject.put(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES.name, it) } + ?.let { + jsonObject.put( + CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES.name, + it.contentToString() + ) + } return jsonObject } From e030039404f09218e2fb855e6255e3fdbba0c328 Mon Sep 17 00:00:00 2001 From: David Jia Date: Mon, 9 Sep 2024 13:38:29 -0700 Subject: [PATCH 07/12] Update CameraXCameraUseCase.kt --- .../core/camera/CameraXCameraUseCase.kt | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt index 2ccc46b1..67828a73 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt @@ -19,9 +19,9 @@ import android.app.Application import android.content.ContentResolver import android.content.ContentValues import android.net.Uri +import android.os.Build import android.os.Environment import android.os.Environment.DIRECTORY_DOCUMENTS -import android.os.SystemClock import android.provider.MediaStore import android.util.Log import androidx.camera.core.CameraInfo @@ -35,18 +35,8 @@ import androidx.camera.core.takePicture import androidx.camera.lifecycle.ProcessCameraProvider import androidx.camera.lifecycle.awaitInstance import androidx.camera.video.Recorder -import androidx.camera.video.Recording -import androidx.camera.video.VideoCapture -import androidx.camera.video.VideoRecordEvent -import androidx.camera.video.VideoRecordEvent.Finalize.ERROR_NONE -import androidx.concurrent.futures.await -import androidx.core.content.ContextCompat -import androidx.core.content.ContextCompat.checkSelfPermission -import androidx.lifecycle.asFlow -import com.google.jetpackcamera.core.camera.CameraUseCase.ScreenFlashEvent.Type import com.google.jetpackcamera.core.camera.DebugCameraInfoUtil.getAllCamerasPropertiesJSONArray import com.google.jetpackcamera.core.camera.DebugCameraInfoUtil.writeFileExternalStorage -import com.google.jetpackcamera.core.camera.effects.SingleSurfaceForcingEffect import com.google.jetpackcamera.settings.SettableConstraintsRepository import com.google.jetpackcamera.settings.model.AspectRatio import com.google.jetpackcamera.settings.model.CameraAppSettings @@ -81,8 +71,8 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import java.io.File import javax.inject.Named private const val TAG = "CameraXCameraUseCase" @@ -99,7 +89,6 @@ class CameraXCameraUseCase @Inject constructor( private val application: Application, - private val coroutineScope: CoroutineScope, @Named("defaultDispatcher") private val defaultDispatcher: CoroutineDispatcher, @Named("iODispatcher")private val iODispatcher: CoroutineDispatcher, private val constraintsRepository: SettableConstraintsRepository From b58b386165d8cf3572de0fae77aaa22a25211df0 Mon Sep 17 00:00:00 2001 From: David Jia Date: Mon, 9 Sep 2024 13:57:32 -0700 Subject: [PATCH 08/12] update --- .../google/jetpackcamera/core/camera/CameraXCameraUseCase.kt | 2 +- .../java/com/google/jetpackcamera/core/common/CommonModule.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt index 67828a73..a927955c 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt @@ -58,6 +58,7 @@ import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale import javax.inject.Inject +import javax.inject.Named import kotlin.properties.Delegates import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.channels.Channel @@ -73,7 +74,6 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.update import kotlinx.coroutines.withContext import java.io.File -import javax.inject.Named private const val TAG = "CameraXCameraUseCase" const val TARGET_FPS_AUTO = 0 diff --git a/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt b/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt index 9ccca8bf..94470793 100644 --- a/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt +++ b/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt @@ -19,12 +19,12 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import javax.inject.Named import javax.inject.Singleton import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob -import javax.inject.Named /** * Dagger [Module] for Common dependencies. From 2afaaf0fd948df81ff7928b36542adcc1a3555cc Mon Sep 17 00:00:00 2001 From: David Jia Date: Mon, 9 Sep 2024 14:16:09 -0700 Subject: [PATCH 09/12] Update CameraXCameraUseCase.kt --- .../google/jetpackcamera/core/camera/CameraXCameraUseCase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt index a927955c..399b01ed 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt @@ -53,6 +53,7 @@ import com.google.jetpackcamera.settings.model.Stabilization import com.google.jetpackcamera.settings.model.SupportedStabilizationMode import com.google.jetpackcamera.settings.model.SystemConstraints import dagger.hilt.android.scopes.ViewModelScoped +import java.io.File import java.io.FileNotFoundException import java.text.SimpleDateFormat import java.util.Calendar @@ -73,7 +74,6 @@ import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.update import kotlinx.coroutines.withContext -import java.io.File private const val TAG = "CameraXCameraUseCase" const val TARGET_FPS_AUTO = 0 From 272b7d7b9c60b88e7ed289761507bd1436c6cf4d Mon Sep 17 00:00:00 2001 From: David Jia Date: Tue, 10 Sep 2024 10:18:54 -0700 Subject: [PATCH 10/12] qualifier --- .../core/camera/CameraXCameraUseCase.kt | 7 ++++--- .../jetpackcamera/core/common/CommonModule.kt | 14 +++++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt index 399b01ed..45d40446 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt @@ -37,6 +37,8 @@ import androidx.camera.lifecycle.awaitInstance import androidx.camera.video.Recorder import com.google.jetpackcamera.core.camera.DebugCameraInfoUtil.getAllCamerasPropertiesJSONArray import com.google.jetpackcamera.core.camera.DebugCameraInfoUtil.writeFileExternalStorage +import com.google.jetpackcamera.core.common.DefaultDispatcher +import com.google.jetpackcamera.core.common.IODispatcher import com.google.jetpackcamera.settings.SettableConstraintsRepository import com.google.jetpackcamera.settings.model.AspectRatio import com.google.jetpackcamera.settings.model.CameraAppSettings @@ -59,7 +61,6 @@ import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale import javax.inject.Inject -import javax.inject.Named import kotlin.properties.Delegates import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.channels.Channel @@ -89,8 +90,8 @@ class CameraXCameraUseCase @Inject constructor( private val application: Application, - @Named("defaultDispatcher") private val defaultDispatcher: CoroutineDispatcher, - @Named("iODispatcher")private val iODispatcher: CoroutineDispatcher, + @DefaultDispatcher private val defaultDispatcher: CoroutineDispatcher, + @IODispatcher private val iODispatcher: CoroutineDispatcher, private val constraintsRepository: SettableConstraintsRepository ) : CameraUseCase { private lateinit var cameraProvider: ProcessCameraProvider diff --git a/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt b/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt index 94470793..cbf3a1c5 100644 --- a/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt +++ b/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt @@ -19,12 +19,12 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import javax.inject.Named import javax.inject.Singleton import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob +import javax.inject.Qualifier /** * Dagger [Module] for Common dependencies. @@ -33,14 +33,22 @@ import kotlinx.coroutines.SupervisorJob @InstallIn(SingletonComponent::class) class CommonModule { @Provides - @Named("defaultDispatcher") + @DefaultDispatcher fun provideDefaultDispatcher(): CoroutineDispatcher = Dispatchers.Default @Provides - @Named("iODispatcher") + @IODispatcher fun provideIODispatcher(): CoroutineDispatcher = Dispatchers.IO @Singleton @Provides fun providesCoroutineScope() = CoroutineScope(SupervisorJob() + Dispatchers.Default) } + +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class DefaultDispatcher + +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class IODispatcher From 62a0c2995bb9c0cff384a5fb5c6033d2fd88dba1 Mon Sep 17 00:00:00 2001 From: David Jia Date: Tue, 10 Sep 2024 11:28:18 -0700 Subject: [PATCH 11/12] Update CommonModule.kt --- .../java/com/google/jetpackcamera/core/common/CommonModule.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt b/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt index cbf3a1c5..2f937430 100644 --- a/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt +++ b/core/common/src/main/java/com/google/jetpackcamera/core/common/CommonModule.kt @@ -19,12 +19,12 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import javax.inject.Qualifier import javax.inject.Singleton import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob -import javax.inject.Qualifier /** * Dagger [Module] for Common dependencies. From 45254d86529adbdec946f18c5c7669ab47e70571 Mon Sep 17 00:00:00 2001 From: David Jia Date: Tue, 10 Sep 2024 16:47:50 -0700 Subject: [PATCH 12/12] address comments --- .../core/camera/CameraXCameraUseCase.kt | 2 +- .../core/camera/DebugCameraInfoUtil.kt | 18 +++++++----------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt index 45d40446..2f7f99a9 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/CameraXCameraUseCase.kt @@ -202,7 +202,7 @@ constructor( getAllCamerasPropertiesJSONArray(cameraProvider.availableCameraInfos).toString() val file = File( Environment.getExternalStoragePublicDirectory(DIRECTORY_DOCUMENTS), - "JCACameraProperties" + "JCACameraProperties.json" ) writeFileExternalStorage(file, cameraProperties) Log.d(TAG, "JCACameraProperties written to ${file.path}. \n$cameraProperties") diff --git a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt index 4dd81032..cb3645ec 100644 --- a/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt +++ b/core/camera/src/main/java/com/google/jetpackcamera/core/camera/DebugCameraInfoUtil.kt @@ -35,19 +35,19 @@ object DebugCameraInfoUtil { fun getAllCamerasPropertiesJSONArray(cameraInfos: List): JSONArray { val result = JSONArray() for (cameraInfo in cameraInfos) { - var camera2cameraInfo = Camera2CameraInfo.from(cameraInfo) - val logicalCameraId = camera2cameraInfo.cameraId + var camera2CameraInfo = Camera2CameraInfo.from(cameraInfo) + val logicalCameraId = camera2CameraInfo.cameraId val logicalCameraData = JSONObject() logicalCameraData.put( "logical-$logicalCameraId", - getCameraPropertiesJSONObject(camera2cameraInfo) + getCameraPropertiesJSONObject(camera2CameraInfo) ) - for (cameraInfo in cameraInfo.physicalCameraInfos) { - camera2cameraInfo = Camera2CameraInfo.from(cameraInfo) - val physicalCameraId = Camera2CameraInfo.from(cameraInfo).cameraId + for (physicalCameraInfo in cameraInfo.physicalCameraInfos) { + camera2CameraInfo = Camera2CameraInfo.from(physicalCameraInfo) + val physicalCameraId = camera2CameraInfo.cameraId logicalCameraData.put( "physical-$physicalCameraId", - getCameraPropertiesJSONObject(camera2cameraInfo) + getCameraPropertiesJSONObject(camera2CameraInfo) ) } result.put(logicalCameraData) @@ -127,13 +127,9 @@ object DebugCameraInfoUtil { return } - var outputStream: FileOutputStream? = null file.createNewFile() - outputStream = FileOutputStream(file, true) - FileOutputStream(file).use { outputStream -> outputStream.write(textToWrite.toByteArray()) } - outputStream.close() } }