[go: nahoru, domu]

blob: 96f7745d2e281f0aa74f4b6d569cc6caf4315475 [file] [log] [blame]
/*
* Copyright (C) 2019 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.core;
import static androidx.camera.core.CameraX.getScaledRect;
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertFalse;
import static junit.framework.TestCase.assertSame;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import android.app.Instrumentation;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Rational;
import android.util.Size;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.camera.core.impl.CameraControlInternal;
import androidx.camera.core.impl.CameraFactory;
import androidx.camera.core.impl.CameraInfoInternal;
import androidx.camera.core.impl.CameraInternal;
import androidx.camera.core.impl.ExtendableUseCaseConfigFactory;
import androidx.camera.core.impl.SessionConfig;
import androidx.camera.core.impl.UseCaseConfigFactory;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.camera.testing.fakes.FakeCamera;
import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
import androidx.camera.testing.fakes.FakeCameraFactory;
import androidx.camera.testing.fakes.FakeCameraInfoInternal;
import androidx.camera.testing.fakes.FakeLifecycleOwner;
import androidx.camera.testing.fakes.FakeUseCase;
import androidx.camera.testing.fakes.FakeUseCaseConfig;
import androidx.core.util.Preconditions;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@MediumTest
@RunWith(AndroidJUnit4.class)
public final class CameraXTest {
@CameraSelector.LensFacing
private static final int CAMERA_LENS_FACING = CameraSelector.LENS_FACING_BACK;
@CameraSelector.LensFacing
private static final int CAMERA_LENS_FACING_FRONT = CameraSelector.LENS_FACING_FRONT;
private static final CameraSelector CAMERA_SELECTOR =
new CameraSelector.Builder().requireLensFacing(CAMERA_LENS_FACING).build();
private static final String CAMERA_ID = "0";
private static final String CAMERA_ID_FRONT = "1";
// A container rect that is 4:3.
private static final RectF CONTAINER_RECT = new RectF(10, 10, 50, 40);
// 1:1 narrow aspect ratio
private static final Rational FIT_ASPECT_RATIO = new Rational(100, 100);
private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
private Context mContext;
private CameraInternal mCameraInternal;
private FakeLifecycleOwner mLifecycle;
private CameraXConfig.Builder mConfigBuilder;
private FakeCameraFactory mFakeCameraFactory;
private UseCaseConfigFactory mUseCaseConfigFactory;
@Before
public void setUp() {
mContext = ApplicationProvider.getApplicationContext();
ExtendableUseCaseConfigFactory defaultConfigFactory = new ExtendableUseCaseConfigFactory();
defaultConfigFactory.installDefaultProvider(FakeUseCaseConfig.class,
cameraInfo -> new FakeUseCaseConfig.Builder().getUseCaseConfig());
mUseCaseConfigFactory = defaultConfigFactory;
mFakeCameraFactory = new FakeCameraFactory();
mCameraInternal = new FakeCamera(mock(CameraControlInternal.class),
new FakeCameraInfoInternal(0, CAMERA_LENS_FACING));
mFakeCameraFactory.insertCamera(CAMERA_LENS_FACING, CAMERA_ID, () -> mCameraInternal);
mConfigBuilder =
new CameraXConfig.Builder()
.setCameraFactoryProvider((ignored0, ignored1) -> mFakeCameraFactory)
.setDeviceSurfaceManagerProvider(ignored ->
new FakeCameraDeviceSurfaceManager())
.setUseCaseConfigFactoryProvider(ignored -> mUseCaseConfigFactory);
mLifecycle = new FakeLifecycleOwner();
}
@After
public void tearDown() throws ExecutionException, InterruptedException {
if (CameraX.isInitialized()) {
mInstrumentation.runOnMainSync(CameraX::unbindAll);
}
CameraX.shutdown().get();
}
@Test
public void viewPortRectWithTwoSurfacesIntersectWide() {
assertThat(
getViewPortRects(
new Size(800, 800),
new Rational(1, 2),
180,
ViewPort.FILL_CENTER,
new Size(400, 800),
new Size(800, 400)))
.isEqualTo(
new Rect[]{
new Rect(100, 200, 300, 600),
new Rect(300, 0, 500, 400)
});
}
@Test
public void viewPortRectWithTwoSurfacesIntersectNarrow() {
assertThat(
getViewPortRects(
new Size(800, 800),
new Rational(2, 1),
180,
ViewPort.FILL_CENTER,
new Size(400, 800),
new Size(800, 400)))
.isEqualTo(
new Rect[]{
new Rect(0, 300, 400, 500),
new Rect(200, 100, 600, 300)
});
}
@Test
public void viewPortRectLandscapeForPortraitModeAndRotate90Degrees() {
assertThat(
getViewPortRects(
new Size(800, 600),
new Rational(400, 300),
90,
ViewPort.FILL_CENTER,
new Size(400, 300)))
.isEqualTo(new Rect[]{
new Rect(88, 0, 313, 300)
});
}
@Test
public void viewPortRectFitStart() {
assertThat(
getViewPortRects(
new Size(800, 600),
new Rational(1, 1),
0,
ViewPort.FIT_END,
new Size(400, 300)))
.isEqualTo(new Rect[]{
new Rect(0, -100, 400, 300)
});
}
/**
* Calls {@link CameraX#calculateViewPortRects(Rect, Rational, int, int, Map)}.
*/
private Rect[] getViewPortRects(Size sensorSize,
Rational aspectRatio,
@IntRange(from = 0, to = 359) int rotationDegree,
@ViewPort.ScaleType int scaleType,
Size... sizes) {
// Convert the sizes into a UseCase map.
List<UseCase> orderedUseCases = new ArrayList<>();
Map<UseCase, Size> useCaseSizeMap = new HashMap<UseCase, Size>() {
{
for (Size size : sizes) {
FakeUseCase fakeUseCase = new FakeUseCaseConfig.Builder().build();
put(fakeUseCase, size);
orderedUseCases.add(fakeUseCase);
}
}
};
Map<UseCase, Rect> useCaseCropRects = CameraX.calculateViewPortRects(
new Rect(0, 0, sensorSize.getWidth(), sensorSize.getHeight()),
aspectRatio,
rotationDegree,
scaleType,
useCaseSizeMap);
// Converts the map back to sizes array.
List<Rect> orderedCropRects = new ArrayList<>();
for (UseCase useCase : orderedUseCases) {
orderedCropRects.add(useCaseCropRects.get(useCase));
}
return orderedCropRects.toArray(new Rect[0]);
}
@Test
public void viewPortRectFillCenter() {
Rect expectedRect = new Rect();
getScaledRect(CONTAINER_RECT, FIT_ASPECT_RATIO, ViewPort.FILL_CENTER).round(expectedRect);
assertThat(expectedRect).isEqualTo(new Rect(15, 10, 45, 40));
}
@Test
public void getScaledRectFillStart() {
Rect expectedRect = new Rect();
getScaledRect(CONTAINER_RECT, FIT_ASPECT_RATIO, ViewPort.FILL_START).round(expectedRect);
assertThat(expectedRect).isEqualTo(new Rect(10, 10, 40, 40));
}
@Test
public void getScaledRectFillEnd() {
Rect expectedRect = new Rect();
getScaledRect(CONTAINER_RECT, FIT_ASPECT_RATIO, ViewPort.FILL_END).round(expectedRect);
assertThat(expectedRect).isEqualTo(new Rect(20, 10, 50, 40));
}
@Test
public void getScaledRectFitCenter() {
Rect expectedRect = new Rect();
getScaledRect(CONTAINER_RECT, FIT_ASPECT_RATIO, ViewPort.FIT_CENTER).round(expectedRect);
assertThat(expectedRect).isEqualTo(new Rect(10, 5, 50, 45));
}
@Test
public void getScaledRectFitStart() {
Rect expectedRect = new Rect();
getScaledRect(CONTAINER_RECT, FIT_ASPECT_RATIO, ViewPort.FIT_START).round(expectedRect);
assertThat(expectedRect).isEqualTo(new Rect(10, 10, 50, 50));
}
@Test
public void getScaledRectFitEnd() {
Rect expectedRect = new Rect();
getScaledRect(CONTAINER_RECT, FIT_ASPECT_RATIO, ViewPort.FIT_END).round(expectedRect);
assertThat(expectedRect).isEqualTo(new Rect(10, 0, 50, 40));
}
@Test
public void rotateUseCasesWith180Degrees_unchanged() {
// Arrange.
UseCase useCase1 = mock(UseCase.class);
UseCase useCase2 = mock(UseCase.class);
Map<UseCase, Size> useCaseSizeMap = new HashMap<UseCase, Size>() {
{
put(useCase1, new Size(800, 600));
put(useCase2, new Size(1600, 900));
}
};
// Assert: return the same set of sizes.
assertThat(CameraX.getRotatedUseCaseSizes(180, useCaseSizeMap)).isEqualTo(useCaseSizeMap);
}
@Test
public void rotateUseCasesWith90Degrees_rotated() {
// Arrange.
UseCase useCase1 = mock(UseCase.class);
UseCase useCase2 = mock(UseCase.class);
Map<UseCase, Size> useCaseSizeMap = new HashMap<UseCase, Size>() {
{
put(useCase1, new Size(800, 600));
put(useCase2, new Size(1600, 900));
}
};
// Assert: return a set of rotated sizes.
assertThat(CameraX.getRotatedUseCaseSizes(90, useCaseSizeMap)).isEqualTo(
new HashMap<UseCase, Size>() {
{
put(useCase1, new Size(600, 800));
put(useCase2, new Size(900, 1600));
}
});
}
@Test
public void initDeinit_success() throws ExecutionException, InterruptedException {
CameraX.initialize(mContext, mConfigBuilder.build()).get();
assertThat(CameraX.isInitialized()).isTrue();
CameraX.shutdown().get();
assertThat(CameraX.isInitialized()).isFalse();
}
@Test
public void failInit_shouldInDeinitState() throws InterruptedException {
// Create an empty config to cause a failed init.
CameraXConfig cameraXConfig = new CameraXConfig.Builder().build();
Exception exception = null;
try {
CameraX.initialize(mContext, cameraXConfig).get();
} catch (ExecutionException e) {
exception = e;
}
assertThat(exception).isInstanceOf(ExecutionException.class);
assertThat(CameraX.isInitialized()).isFalse();
}
@Test
public void reinit_success() throws ExecutionException, InterruptedException {
CameraX.initialize(mContext, mConfigBuilder.build()).get();
assertThat(CameraX.isInitialized()).isTrue();
CameraX.shutdown().get();
assertThat(CameraX.isInitialized()).isFalse();
CameraX.initialize(mContext, mConfigBuilder.build()).get();
assertThat(CameraX.isInitialized()).isTrue();
}
@Test
public void reinit_withPreviousFailedInit() throws ExecutionException, InterruptedException {
// Create an empty config to cause a failed init.
CameraXConfig cameraXConfig = new CameraXConfig.Builder().build();
Exception exception = null;
try {
CameraX.initialize(mContext, cameraXConfig).get();
} catch (ExecutionException e) {
exception = e;
}
assertThat(exception).isInstanceOf(ExecutionException.class);
CameraX.initialize(mContext, mConfigBuilder.build()).get();
assertThat(CameraX.isInitialized()).isTrue();
}
@Test
public void initDeinit_withDirectExecutor() {
mConfigBuilder.setCameraExecutor(CameraXExecutors.directExecutor());
// Don't call Future.get() because its behavior should be the same as synchronous call.
CameraX.initialize(mContext, mConfigBuilder.build());
assertThat(CameraX.isInitialized()).isTrue();
CameraX.shutdown();
assertThat(CameraX.isInitialized()).isFalse();
}
@Test
public void initDeinit_withMultiThreadExecutor()
throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(3);
mConfigBuilder.setCameraExecutor(executorService);
CameraX.initialize(mContext, mConfigBuilder.build()).get();
assertThat(CameraX.isInitialized()).isTrue();
CameraX.shutdown().get();
assertThat(CameraX.isInitialized()).isFalse();
executorService.shutdown();
}
@Test
public void init_withDifferentCameraXConfig() {
CameraFactory cameraFactory0 = new FakeCameraFactory();
CameraFactory.Provider cameraFactoryProvider0 = (ignored0, ignored1) -> cameraFactory0;
CameraFactory cameraFactory1 = new FakeCameraFactory();
CameraFactory.Provider cameraFactoryProvider1 = (ignored0, ignored1) -> cameraFactory1;
mConfigBuilder.setCameraFactoryProvider(cameraFactoryProvider0);
CameraX.initialize(mContext, mConfigBuilder.build());
assertThat(CameraX.getCameraFactory()).isEqualTo(cameraFactory0);
CameraX.shutdown();
mConfigBuilder.setCameraFactoryProvider(cameraFactoryProvider1);
CameraX.initialize(mContext, mConfigBuilder.build());
assertThat(CameraX.getCameraFactory()).isEqualTo(cameraFactory1);
}
@Test
@UiThreadTest
public void bind_createsNewUseCaseGroup() {
initCameraX();
CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR, new FakeUseCase());
// One observer is the use case group. The other observer removes the use case upon the
// lifecycle's destruction.
assertThat(mLifecycle.getObserverCount()).isEqualTo(2);
}
@Test
@UiThreadTest
public void bindMultipleUseCases() {
initCameraX();
FakeUseCase fakeUseCase = new FakeUseCaseConfig.Builder().setTargetName("config0").build();
FakeOtherUseCase fakeOtherUseCase = new FakeOtherUseCaseConfig.Builder().setTargetName(
"config1").build();
CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR, fakeUseCase, fakeOtherUseCase);
assertThat(CameraX.isBound(fakeUseCase)).isTrue();
assertThat(CameraX.isBound(fakeOtherUseCase)).isTrue();
}
@Test
@UiThreadTest
public void isNotBound_afterUnbind() {
initCameraX();
FakeUseCase fakeUseCase = new FakeUseCase();
CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR, fakeUseCase);
CameraX.unbind(fakeUseCase);
assertThat(CameraX.isBound(fakeUseCase)).isFalse();
}
@Test
@UiThreadTest
public void bind_createsDifferentUseCaseGroups_forDifferentLifecycles() {
initCameraX();
CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR,
new FakeUseCaseConfig.Builder().setTargetName("config0").build());
FakeLifecycleOwner anotherLifecycle = new FakeLifecycleOwner();
CameraX.bindToLifecycle(anotherLifecycle, CAMERA_SELECTOR,
new FakeUseCaseConfig.Builder().setTargetName("config1").build());
// One observer is the use case group. The other observer removes the use case upon the
// lifecycle's destruction.
assertThat(mLifecycle.getObserverCount()).isEqualTo(2);
assertThat(anotherLifecycle.getObserverCount()).isEqualTo(2);
}
@Test(expected = IllegalArgumentException.class)
@UiThreadTest
public void exception_withDestroyedLifecycle() {
initCameraX();
FakeUseCase useCase = new FakeUseCase();
mLifecycle.destroy();
CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR, useCase);
}
@Test
@UiThreadTest
public void bind_returnTheSameCameraForSameSelector() {
// This test scope does not include the Extension, so we only bind a fake use case with a
// simple lensFacing selector.
initCameraX();
Camera camera1 = CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR, new FakeUseCase());
Camera camera2 = CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR, new FakeUseCase());
assertSame(camera1, camera2);
}
@Test
@UiThreadTest
public void noException_bindUseCases_withDifferentLensFacing() {
// Initial the front camera for this test.
CameraInternal cameraInternalFront =
new FakeCamera(mock(CameraControlInternal.class),
new FakeCameraInfoInternal(0, CAMERA_LENS_FACING_FRONT));
mFakeCameraFactory.insertCamera(CAMERA_LENS_FACING_FRONT, CAMERA_ID_FRONT,
() -> cameraInternalFront);
CameraXConfig.Builder appConfigBuilder =
new CameraXConfig.Builder()
.setCameraFactoryProvider((ignored0, ignored1) -> mFakeCameraFactory)
.setDeviceSurfaceManagerProvider(ignored ->
new FakeCameraDeviceSurfaceManager())
.setUseCaseConfigFactoryProvider(ignored -> mUseCaseConfigFactory);
CameraX.initialize(mContext, appConfigBuilder.build());
CameraSelector frontSelector =
new CameraSelector.Builder().requireLensFacing(
CameraSelector.LENS_FACING_FRONT).build();
FakeUseCase fakeUseCase = new FakeUseCaseConfig.Builder().build();
CameraSelector backSelector =
new CameraSelector.Builder().requireLensFacing(
CameraSelector.LENS_FACING_BACK).build();
FakeOtherUseCase fakeOtherUseCase = new FakeOtherUseCaseConfig.Builder().build();
boolean hasException = false;
try {
CameraX.bindToLifecycle(mLifecycle, frontSelector, fakeUseCase);
CameraX.bindToLifecycle(mLifecycle, backSelector, fakeOtherUseCase);
} catch (IllegalArgumentException e) {
hasException = true;
}
assertFalse(hasException);
}
@Test
@UiThreadTest
public void bindUseCases_successReturnCamera() {
initCameraX();
FakeUseCaseConfig config0 = new FakeUseCaseConfig.Builder().getUseCaseConfig();
assertThat(CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR,
new FakeUseCase(config0))).isInstanceOf(Camera.class);
}
@Test(expected = IllegalArgumentException.class)
@UiThreadTest
public void bindUseCases_withNotExistedLensFacingCamera() {
initCameraX();
FakeUseCaseConfig config0 = new FakeUseCaseConfig.Builder().getUseCaseConfig();
FakeUseCase fakeUseCase = new FakeUseCase(config0);
// The front camera is not defined, we should get the IllegalArgumentException when it
// tries to get the camera.
CameraX.bindToLifecycle(mLifecycle, CameraSelector.DEFAULT_FRONT_CAMERA, fakeUseCase);
}
@Test
@UiThreadTest
public void bindUseCases_canUpdateUseCase() {
initCameraX();
FakeUseCaseConfig config0 = new FakeUseCaseConfig.Builder().getUseCaseConfig();
FakeUseCase fakeUseCase = new FakeUseCase(config0);
Camera camera = CameraX.bindToLifecycle(mLifecycle, CameraSelector.DEFAULT_BACK_CAMERA,
fakeUseCase);
assertThat(fakeUseCase.getCamera()).isEqualTo(camera);
}
@Test
public void requestingDefaultConfiguration_returnsDefaultConfiguration() {
initCameraX();
// Requesting a default configuration will throw if CameraX is not initialized.
FakeUseCaseConfig config = CameraX.getDefaultUseCaseConfig(FakeUseCaseConfig.class, null);
assertThat(config).isNotNull();
assertThat(config.getTargetClass(null)).isEqualTo(FakeUseCase.class);
}
@Test
@UiThreadTest
public void attachCameraControl_afterBindToLifecycle() {
initCameraX();
FakeUseCaseConfig config0 = new FakeUseCaseConfig.Builder().setTargetName(
"config0").getUseCaseConfig();
AttachCameraFakeCase fakeUseCase = new AttachCameraFakeCase(config0);
CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR, fakeUseCase);
assertThat(fakeUseCase.getCameraControl()).isEqualTo(
mCameraInternal.getCameraControlInternal());
}
@Test
@UiThreadTest
public void onCameraControlReadyIsCalled_afterBindToLifecycle() {
initCameraX();
FakeUseCaseConfig config0 = new FakeUseCaseConfig.Builder().setTargetName(
"config0").getUseCaseConfig();
AttachCameraFakeCase fakeUseCase = spy(new AttachCameraFakeCase(config0));
CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR, fakeUseCase);
Mockito.verify(fakeUseCase).onCameraControlReady();
}
@Test
@UiThreadTest
public void detachCameraControl_afterUnbind() {
initCameraX();
FakeUseCaseConfig config0 = new FakeUseCaseConfig.Builder().setTargetName(
"config0").getUseCaseConfig();
AttachCameraFakeCase fakeUseCase = new AttachCameraFakeCase(config0);
CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR, fakeUseCase);
CameraX.unbind(fakeUseCase);
// after unbind, Camera's CameraControlInternal should be detached from Usecase
assertThat(fakeUseCase.getCameraControl()).isNotEqualTo(
mCameraInternal.getCameraControlInternal());
// UseCase still gets a non-null default CameraControlInternal that does nothing.
assertThat(fakeUseCase.getCameraControl()).isEqualTo(
CameraControlInternal.DEFAULT_EMPTY_INSTANCE);
}
@Test
@UiThreadTest
public void eventCallbackCalled_bindAndUnbind() {
initCameraX();
UseCase.EventCallback eventCallback = Mockito.mock(UseCase.EventCallback.class);
FakeUseCaseConfig.Builder fakeConfigBuilder = new FakeUseCaseConfig.Builder();
fakeConfigBuilder.setUseCaseEventCallback(eventCallback);
AttachCameraFakeCase fakeUseCase = new AttachCameraFakeCase(
fakeConfigBuilder.getUseCaseConfig());
CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR, fakeUseCase);
Mockito.verify(eventCallback).onBind(CAMERA_ID);
CameraX.unbind(fakeUseCase);
Mockito.verify(eventCallback).onUnbind();
}
@Test
public void canRetrieveCameraInfo() {
initCameraX();
CameraInfoInternal cameraInfoInternal = CameraX.getCameraInfo(CAMERA_ID);
assertThat(cameraInfoInternal).isNotNull();
assertThat(cameraInfoInternal.getLensFacing()).isEqualTo(CAMERA_LENS_FACING);
}
@Test
public void canGetCameraXContext() {
initCameraX();
Context context = CameraX.getContext();
assertThat(context).isNotNull();
}
@Test
@UiThreadTest
public void canGetActiveUseCases_afterBindToLifecycle() {
initCameraX();
FakeUseCase fakeUseCase = new FakeUseCaseConfig.Builder().setTargetName("config0").build();
FakeOtherUseCase fakeOtherUseCase = new FakeOtherUseCaseConfig.Builder().setTargetName(
"config1").build();
CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR, fakeUseCase, fakeOtherUseCase);
mLifecycle.startAndResume();
Collection<UseCase> useCases = Preconditions.checkNotNull(CameraX.getActiveUseCases());
assertThat(useCases.contains(fakeUseCase)).isTrue();
assertThat(useCases.contains(fakeOtherUseCase)).isTrue();
}
@Test(expected = IllegalArgumentException.class)
public void cameraInfo_cannotRetrieveCameraInfo_forFrontCamera() {
initCameraX();
// Expect throw the IllegalArgumentException when try to get the cameraInfo from the camera
// which does not exist.
CameraX.getCameraInfo(CAMERA_ID_FRONT);
}
@Test
public void checkHasCameraTrueForExistentCamera() throws CameraInfoUnavailableException {
initCameraX();
assertThat(CameraX.hasCamera(
new CameraSelector.Builder().requireLensFacing(
CameraSelector.LENS_FACING_BACK).build())).isTrue();
}
@Test
public void checkHasCameraFalseForNonexistentCamera() throws CameraInfoUnavailableException {
initCameraX();
assertThat(CameraX.hasCamera(new CameraSelector.Builder().requireLensFacing(
CameraSelector.LENS_FACING_BACK).requireLensFacing(
CameraSelector.LENS_FACING_FRONT).build())).isFalse();
}
private void initCameraX() {
CameraX.initialize(mContext, mConfigBuilder.build());
}
/** FakeUseCase that will call attachToCamera */
public static class AttachCameraFakeCase extends FakeUseCase {
AttachCameraFakeCase(FakeUseCaseConfig config) {
super(config);
}
@Override
@NonNull
protected Size onSuggestedResolutionUpdated(@NonNull Size suggestedResolution) {
SessionConfig.Builder builder = new SessionConfig.Builder();
updateSessionConfig(builder.build());
return suggestedResolution;
}
}
}