| /* |
| * Copyright 2020 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 androidx.camera.camera2.pipe.impl |
| |
| import android.hardware.camera2.CaptureResult |
| import android.os.Build |
| import androidx.camera.camera2.pipe.FrameNumber |
| import androidx.camera.camera2.pipe.RequestNumber |
| import androidx.camera.camera2.pipe.Status3A |
| import androidx.camera.camera2.pipe.testing.CameraPipeRobolectricTestRunner |
| import androidx.camera.camera2.pipe.testing.FakeFrameMetadata |
| import com.google.common.truth.Truth.assertThat |
| import kotlinx.coroutines.ExperimentalCoroutinesApi |
| import org.junit.Test |
| import org.junit.runner.RunWith |
| import org.robolectric.annotation.Config |
| |
| @RunWith(CameraPipeRobolectricTestRunner::class) |
| @Config(minSdk = Build.VERSION_CODES.LOLLIPOP) |
| @OptIn(ExperimentalCoroutinesApi::class) |
| internal class Result3AStateListenerImplTest { |
| @Test |
| fun testWithEmptyExitConditionForKeys() { |
| val listenerForKeys = Result3AStateListenerImpl(mapOf()) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| |
| val frameMetadata = FakeFrameMetadata() |
| |
| listenerForKeys.onRequestSequenceCreated(RequestNumber(2)) |
| |
| // Even though we received an update, the request number is not correct, so the listener |
| // will not be completed. |
| listenerForKeys.update(RequestNumber(1), frameMetadata) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| |
| // Since the key set in listener is empty, any valid update will mark the listener as |
| // completed. |
| listenerForKeys.update(RequestNumber(2), frameMetadata) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isTrue() |
| } |
| |
| @Test |
| fun testWithNoUpdate() { |
| val listenerForKeys = Result3AStateListenerImpl( |
| mapOf( |
| CaptureResult.CONTROL_AF_STATE to |
| listOf( |
| CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED |
| ) |
| ) |
| ) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| } |
| |
| @Test |
| fun testKeyWithUndesirableValueInFrameMetadata() { |
| val listenerForKeys = Result3AStateListenerImpl( |
| mapOf( |
| CaptureResult.CONTROL_AF_STATE to |
| listOf( |
| CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED |
| ) |
| ) |
| ) |
| listenerForKeys.onRequestSequenceCreated(RequestNumber(1)) |
| |
| val frameMetadata = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AF_STATE to CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN |
| ) |
| ) |
| |
| listenerForKeys.update(RequestNumber(1), frameMetadata) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| } |
| |
| @Test |
| fun testKeyWithDesirableValueInFrameMetadata() { |
| val listenerForKeys = Result3AStateListenerImpl( |
| mapOf( |
| CaptureResult.CONTROL_AF_STATE to |
| listOf( |
| CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED |
| ) |
| ) |
| ) |
| listenerForKeys.onRequestSequenceCreated(RequestNumber(1)) |
| |
| val frameMetadata = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AF_STATE to CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED |
| ) |
| ) |
| listenerForKeys.update(RequestNumber(1), frameMetadata) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isTrue() |
| } |
| |
| @Test |
| fun testKeyNotPresentInFrameMetadata() { |
| val listenerForKeys = Result3AStateListenerImpl( |
| mapOf( |
| CaptureResult.CONTROL_AF_STATE to |
| listOf( |
| CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED |
| ) |
| ) |
| ) |
| listenerForKeys.onRequestSequenceCreated(RequestNumber(1)) |
| |
| val frameMetadata = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AE_STATE to CaptureResult.CONTROL_AE_STATE_CONVERGED |
| ) |
| ) |
| listenerForKeys.update(RequestNumber(1), frameMetadata) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| } |
| |
| @Test |
| fun testMultipleKeysWithDesiredValuesInFrameMetadata() { |
| val listenerForKeys = Result3AStateListenerImpl( |
| mapOf( |
| CaptureResult.CONTROL_AF_STATE to |
| listOf( |
| CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED, |
| CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED |
| ), |
| CaptureResult.CONTROL_AE_STATE to listOf(CaptureResult.CONTROL_AE_STATE_LOCKED) |
| ) |
| ) |
| listenerForKeys.onRequestSequenceCreated(RequestNumber(1)) |
| |
| val frameMetadata = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AF_STATE to CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED, |
| CaptureResult.CONTROL_AE_STATE to CaptureResult.CONTROL_AE_STATE_LOCKED |
| ) |
| ) |
| listenerForKeys.update(RequestNumber(1), frameMetadata) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isTrue() |
| } |
| |
| @Test |
| fun testMultipleKeysWithDesiredValuesInFrameMetadataForASubset() { |
| val listenerForKeys = Result3AStateListenerImpl( |
| mapOf( |
| CaptureResult.CONTROL_AF_STATE to |
| listOf( |
| CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED, |
| CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED |
| ), |
| CaptureResult.CONTROL_AE_STATE to listOf(CaptureResult.CONTROL_AE_STATE_LOCKED) |
| ) |
| ) |
| listenerForKeys.onRequestSequenceCreated(RequestNumber(1)) |
| |
| val frameMetadata = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AF_STATE to CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED |
| ) |
| ) |
| listenerForKeys.update(RequestNumber(1), frameMetadata) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| } |
| |
| @Test |
| fun testMultipleUpdates() { |
| val listenerForKeys = Result3AStateListenerImpl( |
| mapOf( |
| CaptureResult.CONTROL_AF_STATE to |
| listOf( |
| CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED, |
| CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED |
| ), |
| CaptureResult.CONTROL_AE_STATE to listOf(CaptureResult.CONTROL_AE_STATE_LOCKED) |
| ) |
| ) |
| listenerForKeys.onRequestSequenceCreated(RequestNumber(1)) |
| |
| val frameMetadata = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AF_STATE to CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED |
| ) |
| ) |
| listenerForKeys.update(RequestNumber(1), frameMetadata) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| |
| val frameMetadata1 = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AF_STATE to CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED, |
| CaptureResult.CONTROL_AE_STATE to CaptureResult.CONTROL_AE_STATE_LOCKED |
| ) |
| ) |
| listenerForKeys.update(RequestNumber(1), frameMetadata1) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isTrue() |
| } |
| |
| @Test |
| fun testTimeLimit() { |
| val listenerForKeys = Result3AStateListenerImpl( |
| exitConditionForKeys = mapOf( |
| CaptureResult.CONTROL_AF_STATE to |
| listOf(CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED) |
| ), |
| timeLimitNs = 1000000000L |
| ) |
| listenerForKeys.onRequestSequenceCreated(RequestNumber(1)) |
| |
| val frameMetadata1 = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AF_STATE to CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN, |
| CaptureResult.SENSOR_TIMESTAMP to 400000000L |
| ) |
| ) |
| listenerForKeys.update(RequestNumber(1), frameMetadata1) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| |
| val frameMetadata2 = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AF_STATE to CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN, |
| CaptureResult.SENSOR_TIMESTAMP to 900000000L |
| ) |
| ) |
| listenerForKeys.update(RequestNumber(1), frameMetadata2) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| |
| val frameMetadata3 = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AF_STATE to CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN, |
| CaptureResult.SENSOR_TIMESTAMP to 1500000000L |
| ) |
| ) |
| listenerForKeys.update(RequestNumber(1), frameMetadata3) |
| val completedDeferred = listenerForKeys.getDeferredResult() |
| assertThat(completedDeferred.isCompleted).isTrue() |
| assertThat(completedDeferred.getCompleted().status).isEqualTo(Status3A.TIME_LIMIT_REACHED) |
| } |
| |
| @Test |
| fun testFrameLimit() { |
| val listenerForKeys = Result3AStateListenerImpl( |
| exitConditionForKeys = mapOf( |
| CaptureResult.CONTROL_AF_STATE to |
| listOf(CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED) |
| ), |
| frameLimit = 10 |
| ) |
| listenerForKeys.onRequestSequenceCreated(RequestNumber(1)) |
| |
| listenerForKeys.onRequestSequenceCreated(RequestNumber(1)) |
| |
| val frameMetadata1 = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AF_STATE to CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN, |
| CaptureResult.SENSOR_TIMESTAMP to 400000000L |
| ), |
| frameNumber = FrameNumber(1) |
| ) |
| listenerForKeys.update(RequestNumber(1), frameMetadata1) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| |
| val frameMetadata2 = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AF_STATE to CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN, |
| CaptureResult.SENSOR_TIMESTAMP to 900000000L |
| ), |
| frameNumber = FrameNumber(3) |
| ) |
| listenerForKeys.update(RequestNumber(1), frameMetadata2) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| |
| val frameMetadata3 = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AF_STATE to CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN, |
| CaptureResult.SENSOR_TIMESTAMP to 1500000000L |
| ), |
| frameNumber = FrameNumber(10) |
| ) |
| listenerForKeys.update(RequestNumber(1), frameMetadata3) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| |
| val frameMetadata4 = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AF_STATE to CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN, |
| CaptureResult.SENSOR_TIMESTAMP to 1700000000L |
| ), |
| frameNumber = FrameNumber(12) |
| ) |
| listenerForKeys.update(RequestNumber(1), frameMetadata4) |
| val completedDeferred = listenerForKeys.getDeferredResult() |
| |
| assertThat(completedDeferred.isCompleted).isTrue() |
| assertThat(completedDeferred.getCompleted().status).isEqualTo(Status3A.FRAME_LIMIT_REACHED) |
| } |
| |
| @Test |
| fun testIgnoreUpdatesFromEarlierRequests() { |
| val listenerForKeys = Result3AStateListenerImpl( |
| mapOf( |
| CaptureResult.CONTROL_AF_STATE to |
| listOf( |
| CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED |
| ) |
| ) |
| ) |
| |
| val frameMetadata = FakeFrameMetadata( |
| resultMetadata = mapOf( |
| CaptureResult.CONTROL_AF_STATE to CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED |
| ) |
| ) |
| // The reference request number of not yet set on the listener, so the update will be |
| // ignored. |
| listenerForKeys.update(RequestNumber(1), frameMetadata) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| |
| // Update the reference request number for this listener. |
| listenerForKeys.onRequestSequenceCreated(RequestNumber(3)) |
| |
| // The update is coming from an earlier request so it will be ignored. |
| listenerForKeys.update(RequestNumber(1), frameMetadata) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| |
| // The update is coming from an earlier request so it will be ignored. |
| listenerForKeys.update(RequestNumber(2), frameMetadata) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isFalse() |
| |
| // The update is from the same or later request number so it will be accepted. |
| listenerForKeys.update(RequestNumber(3), frameMetadata) |
| assertThat(listenerForKeys.getDeferredResult().isCompleted).isTrue() |
| } |
| } |