Skip to content

Commit 968bf87

Browse files
lnishanGerrit Code Review
authored andcommitted
Merge changes Ic048107b,I51a07b11,I53a2a20d into androidx-main
* changes: Add a quirk that waits for onClosed() during camera close Port configAndClose() behavior from CameraX Port CaptureSessionStuckQuirk from CameraX
2 parents 886e0d6 + 1addef5 commit 968bf87

File tree

22 files changed

+468
-46
lines changed

22 files changed

+468
-46
lines changed

camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/testing/TestUseCaseCamera.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,11 @@ class TestUseCaseCamera(
6767
),
6868
) : UseCaseCamera {
6969
val useCaseCameraGraphConfig =
70-
UseCaseCameraConfig(useCases, CameraStateAdapter()).provideUseCaseGraphConfig(
70+
UseCaseCameraConfig(
71+
useCases,
72+
CameraStateAdapter(),
73+
CameraGraph.Flags()
74+
).provideUseCaseGraphConfig(
7175
callbackMap = callbackMap,
7276
cameraConfig = cameraConfig,
7377
cameraPipe = cameraPipe,

camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/CameraQuirks.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ class CameraQuirks @Inject constructor(
8080
if (YuvImageOnePixelShiftQuirk.isEnabled()) {
8181
quirks.add(YuvImageOnePixelShiftQuirk())
8282
}
83+
if (CaptureSessionStuckQuirk.isEnabled()) {
84+
quirks.add(CaptureSessionStuckQuirk())
85+
}
8386

8487
Quirks(quirks)
8588
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* 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.camera2.pipe.integration.compat.quirk
18+
19+
import android.annotation.SuppressLint
20+
import androidx.annotation.RequiresApi
21+
import androidx.camera.core.impl.Quirk
22+
23+
/**
24+
* A quirk to denote the [android.hardware.camera2.CameraCaptureSession] cannot successfully be
25+
* configured if the previous CameraCaptureSession doesn't finish its in-flight capture sequence.
26+
*
27+
* QuirkSummary
28+
* - Bug Id: 146773463
29+
* - Description: Opening and releasing the capture session quickly and constantly is a problem for
30+
* LEGACY devices. It needs to check that all the existing capture sessions have
31+
* finished the processing of their capture sequences before opening the next capture
32+
* session.
33+
* - Device(s): Devices in LEGACY camera hardware level.
34+
*/
35+
@SuppressLint("CameraXQuirksClassDetector")
36+
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
37+
class CaptureSessionStuckQuirk : Quirk {
38+
companion object {
39+
/**
40+
* Always return false as CameraPipe handles this automatically. Please refer to
41+
* [androidx.camera.camera2.pipe.compat.Camera2Quirks.shouldWaitForRepeatingRequest] for
42+
* the conditions under which the quirk will be applied.
43+
*/
44+
fun isEnabled(): Boolean = false
45+
}
46+
}

camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/config/CameraConfig.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import android.hardware.camera2.params.StreamConfigurationMap
2323
import androidx.annotation.Nullable
2424
import androidx.annotation.RequiresApi
2525
import androidx.annotation.VisibleForTesting
26+
import androidx.camera.camera2.pipe.CameraGraph
2627
import androidx.camera.camera2.pipe.CameraId
2728
import androidx.camera.camera2.pipe.CameraMetadata
2829
import androidx.camera.camera2.pipe.CameraPipe
@@ -35,6 +36,8 @@ import androidx.camera.camera2.pipe.integration.compat.Camera2CameraControlCompa
3536
import androidx.camera.camera2.pipe.integration.compat.CameraCompatModule
3637
import androidx.camera.camera2.pipe.integration.compat.EvCompCompat
3738
import androidx.camera.camera2.pipe.integration.compat.ZoomCompat
39+
import androidx.camera.camera2.pipe.integration.compat.quirk.CameraQuirks
40+
import androidx.camera.camera2.pipe.integration.compat.quirk.CaptureSessionStuckQuirk
3841
import androidx.camera.camera2.pipe.integration.impl.CameraPipeCameraProperties
3942
import androidx.camera.camera2.pipe.integration.impl.CameraProperties
4043
import androidx.camera.camera2.pipe.integration.impl.ComboRequestListener
@@ -145,6 +148,16 @@ abstract class CameraModule {
145148
): StreamConfigurationMap? {
146149
return cameraMetadata?.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
147150
}
151+
152+
@CameraScope
153+
@Provides
154+
fun provideCameraGraphFlags(cameraQuirks: CameraQuirks): CameraGraph.Flags {
155+
if (cameraQuirks.quirks.contains(CaptureSessionStuckQuirk::class.java)) {
156+
Log.debug { "CameraPipe should be enabling CaptureSessionStuckQuirk" }
157+
}
158+
// TODO(b/276354253): Set quirkWaitForRepeatingRequestOnDisconnect flag for overrides.
159+
return CameraGraph.Flags()
160+
}
148161
}
149162

150163
@Binds

camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/config/UseCaseCameraConfig.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ abstract class UseCaseCameraModule {
8282
class UseCaseCameraConfig(
8383
private val useCases: List<UseCase>,
8484
private val cameraStateAdapter: CameraStateAdapter,
85+
private val cameraGraphFlags: CameraGraph.Flags,
8586
) {
8687
@UseCaseCameraScope
8788
@Provides
@@ -142,6 +143,7 @@ class UseCaseCameraConfig(
142143
camera = cameraConfig.cameraId,
143144
streams = streamConfigMap.keys.toList(),
144145
defaultListeners = listOf(callbackMap, requestListener),
146+
flags = cameraGraphFlags,
145147
)
146148
)
147149

camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import android.media.MediaCodec
2020
import android.os.Build
2121
import androidx.annotation.GuardedBy
2222
import androidx.annotation.RequiresApi
23+
import androidx.camera.camera2.pipe.CameraGraph
2324
import androidx.camera.camera2.pipe.core.Log
2425
import androidx.camera.camera2.pipe.integration.adapter.CameraStateAdapter
2526
import androidx.camera.camera2.pipe.integration.config.CameraConfig
@@ -71,6 +72,7 @@ class UseCaseManager @Inject constructor(
7172
private val controls: java.util.Set<UseCaseCameraControl>,
7273
private val camera2CameraControl: Camera2CameraControl,
7374
private val cameraStateAdapter: CameraStateAdapter,
75+
private val cameraGraphFlags: CameraGraph.Flags,
7476
cameraProperties: CameraProperties,
7577
displayInfoManager: DisplayInfoManager,
7678
) {
@@ -254,7 +256,9 @@ class UseCaseManager @Inject constructor(
254256
}
255257

256258
// Create and configure the new camera component.
257-
_activeComponent = builder.config(UseCaseCameraConfig(useCases, cameraStateAdapter)).build()
259+
_activeComponent =
260+
builder.config(UseCaseCameraConfig(useCases, cameraStateAdapter, cameraGraphFlags))
261+
.build()
258262
for (control in allControls) {
259263
control.useCaseCamera = camera
260264
}
@@ -277,6 +281,7 @@ class UseCaseManager @Inject constructor(
277281

278282
return !meteringRepeatingEnabled && (onlyVideoCapture || requireMeteringRepeating)
279283
}
284+
280285
@GuardedBy("lock")
281286
private fun addRepeatingUseCase() {
282287
meteringRepeating.setupSession()

camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package androidx.camera.camera2.pipe.integration.impl
1818

1919
import android.os.Build
2020
import android.util.Size
21+
import androidx.camera.camera2.pipe.CameraGraph
2122
import androidx.camera.camera2.pipe.CameraId
2223
import androidx.camera.camera2.pipe.integration.adapter.CameraStateAdapter
2324
import androidx.camera.camera2.pipe.integration.adapter.RobolectricCameraPipeTestRunner
@@ -274,6 +275,7 @@ class UseCaseManagerTest {
274275
ComboRequestListener()
275276
),
276277
cameraStateAdapter = CameraStateAdapter(),
278+
cameraGraphFlags = CameraGraph.Flags(),
277279
displayInfoManager = DisplayInfoManager(ApplicationProvider.getApplicationContext()),
278280
).also {
279281
useCaseManagerList.add(it)
@@ -282,7 +284,7 @@ class UseCaseManagerTest {
282284
private fun createImageCapture(): ImageCapture =
283285
ImageCapture.Builder()
284286
.setCaptureOptionUnpacker { _, _ -> }
285-
.setSessionOptionUnpacker() { _, _, _ -> }
287+
.setSessionOptionUnpacker { _, _, _ -> }
286288
.build().also {
287289
it.simulateActivation()
288290
useCaseList.add(it)
@@ -291,7 +293,7 @@ class UseCaseManagerTest {
291293
private fun createPreview(): Preview =
292294
Preview.Builder()
293295
.setCaptureOptionUnpacker { _, _ -> }
294-
.setSessionOptionUnpacker() { _, _, _ -> }
296+
.setSessionOptionUnpacker { _, _, _ -> }
295297
.build().apply {
296298
setSurfaceProvider(
297299
CameraXExecutors.mainThreadExecutor(),

camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeUseCaseCamera.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ import kotlinx.coroutines.Job
4040
import kotlinx.coroutines.withTimeoutOrNull
4141

4242
class FakeUseCaseCameraComponentBuilder : UseCaseCameraComponent.Builder {
43-
private var config: UseCaseCameraConfig = UseCaseCameraConfig(emptyList(), CameraStateAdapter())
43+
private var config: UseCaseCameraConfig =
44+
UseCaseCameraConfig(emptyList(), CameraStateAdapter(), CameraGraph.Flags())
4445

4546
override fun config(config: UseCaseCameraConfig): UseCaseCameraComponent.Builder {
4647
this.config = config

camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,22 @@ interface CameraGraph : AutoCloseable {
135135
data class Flags(
136136
val configureBlankSessionOnStop: Boolean = false,
137137
val abortCapturesOnStop: Boolean = false,
138-
val allowMultipleActiveCameras: Boolean = false
138+
val allowMultipleActiveCameras: Boolean = false,
139+
140+
/**
141+
* A quirk that waits for the last repeating capture request to start before stopping the
142+
* current capture session. Please refer to the bugs linked here, or
143+
* [androidx.camera.camera2.pipe.compat.Camera2Quirks.shouldWaitForRepeatingRequest] for
144+
* more information.
145+
*
146+
* This flag provides the overrides for you to override the default behavior (CameraPipe
147+
* would turn on/off the quirk automatically based on device information).
148+
*
149+
* - Bug(s): b/146773463, b/267557892
150+
* - Device(s): Camera devices on hardware level LEGACY
151+
* - API levels: All
152+
*/
153+
val quirkWaitForRepeatingRequestOnDisconnect: Boolean? = null,
139154
)
140155

141156
enum class OperatingMode {

camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraController.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ constructor(
5757
private val captureSequenceProcessorFactory: Camera2CaptureSequenceProcessorFactory,
5858
private val virtualCameraManager: VirtualCameraManager,
5959
private val cameraSurfaceManager: CameraSurfaceManager,
60-
private val timeSource: TimeSource
60+
private val timeSource: TimeSource,
6161
) : CameraController {
6262
override val cameraId: CameraId
6363
get() = config.camera

0 commit comments

Comments
 (0)