Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit 87c3989

Browse files
mvanbeusekomacoutts
andcommitted
Added Android AutoFocus feature
Co-authored-by: Andrew Coutts <[email protected]>
1 parent 9fb888f commit 87c3989

File tree

5 files changed

+324
-1
lines changed

5 files changed

+324
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package io.flutter.plugins.camera.features.autofocus;
6+
7+
import android.hardware.camera2.CameraCharacteristics;
8+
import android.hardware.camera2.CaptureRequest;
9+
import io.flutter.plugins.camera.CameraProperties;
10+
import io.flutter.plugins.camera.features.CameraFeature;
11+
12+
public class AutoFocusFeature extends CameraFeature<FocusMode> {
13+
private FocusMode currentSetting = FocusMode.auto;
14+
15+
// When we switch recording modes we re-create this feature with
16+
// the appropriate setting here.
17+
private final boolean recordingVideo;
18+
19+
public AutoFocusFeature(CameraProperties cameraProperties, boolean recordingVideo) {
20+
super(cameraProperties);
21+
this.recordingVideo = recordingVideo;
22+
}
23+
24+
@Override
25+
public String getDebugName() {
26+
return "AutoFocusFeature";
27+
}
28+
29+
@Override
30+
public FocusMode getValue() {
31+
return currentSetting;
32+
}
33+
34+
@Override
35+
public void setValue(FocusMode value) {
36+
this.currentSetting = value;
37+
}
38+
39+
@Override
40+
public boolean checkIsSupported() {
41+
int[] modes = cameraProperties.getControlAutoFocusAvailableModes();
42+
43+
// Check if fixed focal length lens. If LENS_INFO_MINIMUM_FOCUS_DISTANCE=0, then this is fixed.
44+
// Can be null on some devices.
45+
final Float minFocus = cameraProperties.getLensInfoMinimumFocusDistance();
46+
// final Float maxFocus = cameraCharacteristics.get(CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE);
47+
48+
// Value can be null on some devices:
49+
// https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE
50+
boolean isFixedLength;
51+
if (minFocus == null) {
52+
isFixedLength = true;
53+
} else {
54+
isFixedLength = minFocus == 0;
55+
}
56+
57+
return !isFixedLength
58+
&& !(modes.length == 0
59+
|| (modes.length == 1 && modes[0] == CameraCharacteristics.CONTROL_AF_MODE_OFF));
60+
}
61+
62+
@Override
63+
public void updateBuilder(CaptureRequest.Builder requestBuilder) {
64+
if (!checkIsSupported()) {
65+
return;
66+
}
67+
68+
switch (currentSetting) {
69+
case locked:
70+
/** If we're locking AF we should do a one-time focus, then set the AF to idle */
71+
requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
72+
break;
73+
74+
case auto:
75+
requestBuilder.set(
76+
CaptureRequest.CONTROL_AF_MODE,
77+
recordingVideo
78+
? CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO
79+
: CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
80+
default:
81+
break;
82+
}
83+
}
84+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package io.flutter.plugins.camera.features.autofocus;
6+
7+
// Mirrors focus_mode.dart
8+
public enum FocusMode {
9+
auto("auto"),
10+
locked("locked");
11+
12+
private final String strValue;
13+
14+
FocusMode(String strValue) {
15+
this.strValue = strValue;
16+
}
17+
18+
public static FocusMode getValueForString(String modeStr) {
19+
for (FocusMode value : values()) {
20+
if (value.strValue.equals(modeStr)) return value;
21+
}
22+
return null;
23+
}
24+
25+
@Override
26+
public String toString() {
27+
return strValue;
28+
}
29+
}

packages/camera/camera/android/src/test/java/io/flutter/plugins/camera/CameraPropertiesImplTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -277,4 +277,4 @@ public void getAvailableNoiseReductionModesTest() {
277277
.get(CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES);
278278
assertEquals(actualReductionModes, expectedReductionModes);
279279
}
280-
}
280+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package io.flutter.plugins.camera.features.autofocus;
6+
7+
import static org.junit.Assert.assertEquals;
8+
import static org.junit.Assert.assertFalse;
9+
import static org.junit.Assert.assertTrue;
10+
import static org.mockito.ArgumentMatchers.any;
11+
import static org.mockito.Mockito.mock;
12+
import static org.mockito.Mockito.never;
13+
import static org.mockito.Mockito.times;
14+
import static org.mockito.Mockito.verify;
15+
import static org.mockito.Mockito.when;
16+
17+
import android.hardware.camera2.CameraCharacteristics;
18+
import android.hardware.camera2.CaptureRequest;
19+
import io.flutter.plugins.camera.CameraProperties;
20+
import org.junit.Test;
21+
22+
public class AutoFocusFeatureTest {
23+
private static final int[] FOCUS_MODES_ONLY_OFF =
24+
new int[] {CameraCharacteristics.CONTROL_AF_MODE_OFF};
25+
private static final int[] FOCUS_MODES =
26+
new int[] {
27+
CameraCharacteristics.CONTROL_AF_MODE_OFF, CameraCharacteristics.CONTROL_AF_MODE_AUTO
28+
};
29+
30+
@Test
31+
public void getDebugName_should_return_the_name_of_the_feature() {
32+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
33+
AutoFocusFeature autoFocusFeature = new AutoFocusFeature(mockCameraProperties, false);
34+
35+
assertEquals("AutoFocusFeature", autoFocusFeature.getDebugName());
36+
}
37+
38+
@Test
39+
public void getValue_should_return_auto_if_not_set() {
40+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
41+
AutoFocusFeature autoFocusFeature = new AutoFocusFeature(mockCameraProperties, false);
42+
43+
assertEquals(FocusMode.auto, autoFocusFeature.getValue());
44+
}
45+
46+
@Test
47+
public void getValue_should_echo_the_set_value() {
48+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
49+
AutoFocusFeature autoFocusFeature = new AutoFocusFeature(mockCameraProperties, false);
50+
FocusMode expectedValue = FocusMode.locked;
51+
52+
autoFocusFeature.setValue(expectedValue);
53+
FocusMode actualValue = autoFocusFeature.getValue();
54+
55+
assertEquals(expectedValue, actualValue);
56+
}
57+
58+
@Test
59+
public void checkIsSupported_should_return_false_when_minimum_focus_distance_is_zero() {
60+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
61+
AutoFocusFeature autoFocusFeature = new AutoFocusFeature(mockCameraProperties, false);
62+
63+
when(mockCameraProperties.getControlAutoFocusAvailableModes()).thenReturn(FOCUS_MODES);
64+
when(mockCameraProperties.getLensInfoMinimumFocusDistance()).thenReturn(0.0F);
65+
66+
assertFalse(autoFocusFeature.checkIsSupported());
67+
}
68+
69+
@Test
70+
public void checkIsSupported_should_return_false_when_minimum_focus_distance_is_null() {
71+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
72+
AutoFocusFeature autoFocusFeature = new AutoFocusFeature(mockCameraProperties, false);
73+
74+
when(mockCameraProperties.getControlAutoFocusAvailableModes()).thenReturn(FOCUS_MODES);
75+
when(mockCameraProperties.getLensInfoMinimumFocusDistance()).thenReturn(null);
76+
77+
assertFalse(autoFocusFeature.checkIsSupported());
78+
}
79+
80+
@Test
81+
public void checkIsSupport_should_return_false_when_no_focus_modes_are_available() {
82+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
83+
AutoFocusFeature autoFocusFeature = new AutoFocusFeature(mockCameraProperties, false);
84+
85+
when(mockCameraProperties.getControlAutoFocusAvailableModes()).thenReturn(new int[] {});
86+
when(mockCameraProperties.getLensInfoMinimumFocusDistance()).thenReturn(1.0F);
87+
88+
assertFalse(autoFocusFeature.checkIsSupported());
89+
}
90+
91+
@Test
92+
public void checkIsSupport_should_return_false_when_only_focus_off_is_available() {
93+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
94+
AutoFocusFeature autoFocusFeature = new AutoFocusFeature(mockCameraProperties, false);
95+
96+
when(mockCameraProperties.getControlAutoFocusAvailableModes()).thenReturn(FOCUS_MODES_ONLY_OFF);
97+
when(mockCameraProperties.getLensInfoMinimumFocusDistance()).thenReturn(1.0F);
98+
99+
assertFalse(autoFocusFeature.checkIsSupported());
100+
}
101+
102+
@Test
103+
public void checkIsSupport_should_return_true_when_only_multiple_focus_modes_are_available() {
104+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
105+
AutoFocusFeature autoFocusFeature = new AutoFocusFeature(mockCameraProperties, false);
106+
107+
when(mockCameraProperties.getControlAutoFocusAvailableModes()).thenReturn(FOCUS_MODES);
108+
when(mockCameraProperties.getLensInfoMinimumFocusDistance()).thenReturn(1.0F);
109+
110+
assertTrue(autoFocusFeature.checkIsSupported());
111+
}
112+
113+
@Test
114+
public void updateBuilder_should_return_when_checkIsSupported_is_false() {
115+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
116+
CaptureRequest.Builder mockBuilder = mock(CaptureRequest.Builder.class);
117+
AutoFocusFeature autoFocusFeature = new AutoFocusFeature(mockCameraProperties, false);
118+
119+
when(mockCameraProperties.getControlAutoFocusAvailableModes()).thenReturn(FOCUS_MODES);
120+
when(mockCameraProperties.getLensInfoMinimumFocusDistance()).thenReturn(0.0F);
121+
122+
autoFocusFeature.updateBuilder(mockBuilder);
123+
124+
verify(mockBuilder, never()).set(any(), any());
125+
}
126+
127+
@Test
128+
public void updateBuilder_should_set_control_mode_to_auto_when_focus_is_locked() {
129+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
130+
CaptureRequest.Builder mockBuilder = mock(CaptureRequest.Builder.class);
131+
AutoFocusFeature autoFocusFeature = new AutoFocusFeature(mockCameraProperties, false);
132+
133+
when(mockCameraProperties.getControlAutoFocusAvailableModes()).thenReturn(FOCUS_MODES);
134+
when(mockCameraProperties.getLensInfoMinimumFocusDistance()).thenReturn(1.0F);
135+
136+
autoFocusFeature.setValue(FocusMode.locked);
137+
autoFocusFeature.updateBuilder(mockBuilder);
138+
139+
verify(mockBuilder, times(1))
140+
.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
141+
}
142+
143+
@Test
144+
public void
145+
updateBuilder_should_set_control_mode_to_continuous_video_when_focus_is_auto_and_recording_video() {
146+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
147+
CaptureRequest.Builder mockBuilder = mock(CaptureRequest.Builder.class);
148+
AutoFocusFeature autoFocusFeature = new AutoFocusFeature(mockCameraProperties, true);
149+
150+
when(mockCameraProperties.getControlAutoFocusAvailableModes()).thenReturn(FOCUS_MODES);
151+
when(mockCameraProperties.getLensInfoMinimumFocusDistance()).thenReturn(1.0F);
152+
153+
autoFocusFeature.setValue(FocusMode.auto);
154+
autoFocusFeature.updateBuilder(mockBuilder);
155+
156+
verify(mockBuilder, times(1))
157+
.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO);
158+
}
159+
160+
@Test
161+
public void
162+
updateBuilder_should_set_control_mode_to_continuous_video_when_focus_is_auto_and_not_recording_video() {
163+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
164+
CaptureRequest.Builder mockBuilder = mock(CaptureRequest.Builder.class);
165+
AutoFocusFeature autoFocusFeature = new AutoFocusFeature(mockCameraProperties, false);
166+
167+
when(mockCameraProperties.getControlAutoFocusAvailableModes()).thenReturn(FOCUS_MODES);
168+
when(mockCameraProperties.getLensInfoMinimumFocusDistance()).thenReturn(1.0F);
169+
170+
autoFocusFeature.setValue(FocusMode.auto);
171+
autoFocusFeature.updateBuilder(mockBuilder);
172+
173+
verify(mockBuilder, times(1))
174+
.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
175+
}
176+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package io.flutter.plugins.camera.features.autofocus;
6+
7+
import static org.junit.Assert.assertEquals;
8+
9+
import org.junit.Test;
10+
11+
public class FocusModeTest {
12+
13+
@Test
14+
public void getValueForString_returns_correct_values() {
15+
assertEquals(
16+
"Returns FocusMode.auto for 'auto'", FocusMode.getValueForString("auto"), FocusMode.auto);
17+
assertEquals(
18+
"Returns FocusMode.locked for 'locked'",
19+
FocusMode.getValueForString("locked"),
20+
FocusMode.locked);
21+
}
22+
23+
@Test
24+
public void getValueForString_returns_null_for_nonexistant_value() {
25+
assertEquals(
26+
"Returns null for 'nonexistant'", FocusMode.getValueForString("nonexistant"), null);
27+
}
28+
29+
@Test
30+
public void toString_returns_correct_value() {
31+
assertEquals("Returns 'auto' for FocusMode.auto", FocusMode.auto.toString(), "auto");
32+
assertEquals("Returns 'locked' for FocusMode.locked", FocusMode.locked.toString(), "locked");
33+
}
34+
}

0 commit comments

Comments
 (0)