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