1 /* <lambda>null2 * Copyright 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.camera.integration.core 18 19 import android.content.Context 20 import android.os.Build 21 import androidx.camera.camera2.Camera2Config 22 import androidx.camera.camera2.pipe.integration.CameraPipeConfig 23 import androidx.camera.core.CameraInfo 24 import androidx.camera.core.CameraSelector 25 import androidx.camera.core.CameraXConfig 26 import androidx.camera.core.DynamicRange 27 import androidx.camera.lifecycle.ProcessCameraProvider 28 import androidx.camera.testing.impl.CameraPipeConfigTestRule 29 import androidx.camera.testing.impl.CameraUtil 30 import androidx.camera.testing.impl.CoreAppTestUtil 31 import androidx.concurrent.futures.await 32 import androidx.test.core.app.ApplicationProvider 33 import androidx.test.filters.LargeTest 34 import androidx.test.filters.SdkSuppress 35 import androidx.testutils.assertThrows 36 import com.google.common.truth.Truth.assertThat 37 import com.google.common.truth.Truth.assertWithMessage 38 import java.util.concurrent.TimeUnit 39 import kotlinx.coroutines.runBlocking 40 import kotlinx.coroutines.withTimeout 41 import org.junit.After 42 import org.junit.Assume.assumeTrue 43 import org.junit.Before 44 import org.junit.Rule 45 import org.junit.Test 46 import org.junit.runner.RunWith 47 import org.junit.runners.Parameterized 48 49 @LargeTest 50 @RunWith(Parameterized::class) 51 class CameraInfoDeviceTest(private val implName: String, private val cameraXConfig: CameraXConfig) { 52 @get:Rule 53 val useCamera = 54 CameraUtil.grantCameraPermissionAndPreTestAndPostTest( 55 CameraUtil.PreTestCameraIdList( 56 if (implName == Camera2Config::class.simpleName) { 57 Camera2Config.defaultConfig() 58 } else { 59 CameraPipeConfig.defaultConfig() 60 } 61 ) 62 ) 63 64 @get:Rule 65 val cameraPipeConfigTestRule = 66 CameraPipeConfigTestRule( 67 active = implName == CameraPipeConfig::class.simpleName, 68 ) 69 70 private val context = ApplicationProvider.getApplicationContext<Context>() 71 private lateinit var cameraProvider: ProcessCameraProvider 72 73 companion object { 74 @JvmStatic 75 @Parameterized.Parameters(name = "{0}") 76 fun data() = 77 listOf( 78 arrayOf(Camera2Config::class.simpleName, Camera2Config.defaultConfig()), 79 arrayOf(CameraPipeConfig::class.simpleName, CameraPipeConfig.defaultConfig()) 80 ) 81 } 82 83 @Before 84 fun setUp() = runBlocking { 85 assumeTrue(CameraUtil.deviceHasCamera()) 86 CoreAppTestUtil.assumeCompatibleDevice() 87 88 withTimeout(10000) { 89 ProcessCameraProvider.configureInstance(cameraXConfig) 90 cameraProvider = ProcessCameraProvider.getInstance(context).await() 91 } 92 } 93 94 @After 95 fun tearDown() { 96 if (::cameraProvider.isInitialized) { 97 cameraProvider.shutdownAsync()[10, TimeUnit.SECONDS] 98 } 99 } 100 101 @Test 102 fun allCamerasAdvertiseSdr() { 103 cameraProvider.availableCameraInfos.forEach { cameraInfo -> 104 assertThat(cameraInfo.querySupportedDynamicRanges(setOf(DynamicRange.UNSPECIFIED))) 105 .contains(DynamicRange.SDR) 106 } 107 } 108 109 @Test 110 fun underSpecifiedDynamicRange_neverReturnedFromQuery() { 111 cameraProvider.availableCameraInfos.forEach { cameraInfo -> 112 cameraInfo.querySupportedDynamicRanges(setOf(DynamicRange.UNSPECIFIED)).forEach { 113 assertWithMessage("$cameraInfo advertises under-specified dynamic range: $it") 114 .that(it.isFullySpecified) 115 .isTrue() 116 } 117 } 118 } 119 120 @Test 121 fun emptyCandidateDynamicRangeSet_throwsIllegalArgumentException() { 122 cameraProvider.availableCameraInfos.forEach { cameraInfo -> 123 assertThrows(IllegalArgumentException::class.java) { 124 cameraInfo.querySupportedDynamicRanges(emptySet()) 125 } 126 } 127 } 128 129 @Test 130 @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM - 1) 131 fun isTorchStrengthLevelSupported_returnFalseWhenApiNotMet() { 132 assertThat( 133 cameraProvider 134 .getCameraInfo(CameraSelector.DEFAULT_BACK_CAMERA) 135 .isTorchStrengthSupported 136 ) 137 .isFalse() 138 } 139 140 @Test 141 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) 142 fun getMaxTorchStrengthLevel_greaterThanOneWhenSupported() { 143 val cameraInfo = cameraProvider.getCameraInfo(CameraSelector.DEFAULT_BACK_CAMERA) 144 assumeTrue(cameraInfo.isTorchStrengthSupported) 145 146 assertThat(cameraInfo.maxTorchStrengthLevel).isGreaterThan(1) 147 } 148 149 @Test 150 fun getMaxTorchStrengthLevel_returnUnsupported() { 151 val cameraInfo = cameraProvider.getCameraInfo(CameraSelector.DEFAULT_BACK_CAMERA) 152 assumeTrue(!cameraInfo.isTorchStrengthSupported) 153 154 assertThat(cameraInfo.maxTorchStrengthLevel) 155 .isEqualTo(CameraInfo.TORCH_STRENGTH_LEVEL_UNSUPPORTED) 156 } 157 158 @Test 159 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) 160 fun getTorchStrengthLevel_returnValidValueWhenSupported() { 161 val cameraInfo = cameraProvider.getCameraInfo(CameraSelector.DEFAULT_BACK_CAMERA) 162 assumeTrue(cameraInfo.isTorchStrengthSupported) 163 164 val torchStrengthLevel = cameraInfo.torchStrengthLevel.value 165 assertThat(torchStrengthLevel).isAtMost(cameraInfo.maxTorchStrengthLevel) 166 assertThat(torchStrengthLevel).isAtLeast(1) 167 } 168 169 @Test 170 fun getTorchStrengthLevel_returnUnsupported() { 171 val cameraInfo = cameraProvider.getCameraInfo(CameraSelector.DEFAULT_BACK_CAMERA) 172 assumeTrue(!cameraInfo.isTorchStrengthSupported) 173 174 assertThat(cameraInfo.torchStrengthLevel.value) 175 .isEqualTo(CameraInfo.TORCH_STRENGTH_LEVEL_UNSUPPORTED) 176 } 177 } 178