blob: b1b89c545b188fc3429f351ce6444d8ba9990a51 [file] [log] [blame]
/*
* Copyright 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.camera2.impl;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.os.Build;
import android.view.Surface;
import androidx.camera.core.CameraInfoInternal;
import androidx.camera.core.CameraInfoUnavailableException;
import androidx.camera.core.LensFacing;
import androidx.lifecycle.MutableLiveData;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.internal.DoNotInstrument;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowCameraCharacteristics;
import org.robolectric.shadows.ShadowCameraManager;
@SmallTest
@RunWith(RobolectricTestRunner.class)
@DoNotInstrument
@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
public class Camera2CameraInfoTest {
private static final String CAMERA0_ID = "0";
private static final int CAMERA0_SENSOR_ORIENTATION = 90;
private static final LensFacing CAMERA0_LENS_FACING_ENUM = LensFacing.BACK;
private static final int CAMERA0_LENS_FACING_INT = CameraCharacteristics.LENS_FACING_BACK;
private static final boolean CAMERA0_FLASH_INFO_BOOLEAN = true;
private static final String CAMERA1_ID = "1";
private static final int CAMERA1_SENSOR_ORIENTATION = 0;
private static final int CAMERA1_LENS_FACING_INT = CameraCharacteristics.LENS_FACING_FRONT;
private static final boolean CAMERA1_FLASH_INFO_BOOLEAN = false;
private static final int FAKE_SUPPORTED_HARDWARE_LEVEL =
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3;
private CameraManager mCameraManager;
@Before
public void setUp() {
initCameras();
mCameraManager =
(CameraManager) ApplicationProvider.getApplicationContext().getSystemService(
Context.CAMERA_SERVICE);
}
@Test
public void canCreateCameraInfo() throws CameraInfoUnavailableException {
CameraInfoInternal cameraInfoInternal = new Camera2CameraInfo(mCameraManager, CAMERA0_ID,
mock(ZoomControl.class));
assertThat(cameraInfoInternal).isNotNull();
}
@Test
public void cameraInfo_canReturnSensorOrientation() throws CameraInfoUnavailableException {
CameraInfoInternal cameraInfoInternal = new Camera2CameraInfo(mCameraManager, CAMERA0_ID,
mock(ZoomControl.class));
assertThat(cameraInfoInternal.getSensorRotationDegrees()).isEqualTo(
CAMERA0_SENSOR_ORIENTATION);
}
@Test
public void cameraInfo_canCalculateCorrectRelativeRotation_forBackCamera()
throws CameraInfoUnavailableException {
CameraInfoInternal cameraInfoInternal = new Camera2CameraInfo(mCameraManager, CAMERA0_ID,
mock(ZoomControl.class));
// Note: these numbers depend on the camera being a back-facing camera.
assertThat(cameraInfoInternal.getSensorRotationDegrees(Surface.ROTATION_0))
.isEqualTo(CAMERA0_SENSOR_ORIENTATION);
assertThat(cameraInfoInternal.getSensorRotationDegrees(Surface.ROTATION_90))
.isEqualTo((CAMERA0_SENSOR_ORIENTATION - 90 + 360) % 360);
assertThat(cameraInfoInternal.getSensorRotationDegrees(Surface.ROTATION_180))
.isEqualTo((CAMERA0_SENSOR_ORIENTATION - 180 + 360) % 360);
assertThat(cameraInfoInternal.getSensorRotationDegrees(Surface.ROTATION_270))
.isEqualTo((CAMERA0_SENSOR_ORIENTATION - 270 + 360) % 360);
}
@Test
public void cameraInfo_canCalculateCorrectRelativeRotation_forFrontCamera()
throws CameraInfoUnavailableException {
CameraInfoInternal cameraInfoInternal = new Camera2CameraInfo(mCameraManager, CAMERA1_ID,
mock(ZoomControl.class));
// Note: these numbers depend on the camera being a front-facing camera.
assertThat(cameraInfoInternal.getSensorRotationDegrees(Surface.ROTATION_0))
.isEqualTo(CAMERA1_SENSOR_ORIENTATION);
assertThat(cameraInfoInternal.getSensorRotationDegrees(Surface.ROTATION_90))
.isEqualTo((CAMERA1_SENSOR_ORIENTATION + 90) % 360);
assertThat(cameraInfoInternal.getSensorRotationDegrees(Surface.ROTATION_180))
.isEqualTo((CAMERA1_SENSOR_ORIENTATION + 180) % 360);
assertThat(cameraInfoInternal.getSensorRotationDegrees(Surface.ROTATION_270))
.isEqualTo((CAMERA1_SENSOR_ORIENTATION + 270) % 360);
}
@Test
public void cameraInfo_canReturnLensFacing() throws CameraInfoUnavailableException {
CameraInfoInternal cameraInfoInternal = new Camera2CameraInfo(mCameraManager, CAMERA0_ID,
mock(ZoomControl.class));
assertThat(cameraInfoInternal.getLensFacing()).isEqualTo(CAMERA0_LENS_FACING_ENUM);
}
@Test
public void cameraInfo_canReturnFlashAvailable_forBackCamera()
throws CameraInfoUnavailableException {
CameraInfoInternal cameraInfoInternal = new Camera2CameraInfo(mCameraManager, CAMERA0_ID,
mock(ZoomControl.class));
assertThat(cameraInfoInternal.isFlashAvailable().getValue().booleanValue()).isEqualTo(
CAMERA0_FLASH_INFO_BOOLEAN);
}
@Test
public void cameraInfo_canReturnFlashAvailable_forFrontCamera()
throws CameraInfoUnavailableException {
CameraInfoInternal cameraInfoInternal = new Camera2CameraInfo(mCameraManager, CAMERA1_ID,
mock(ZoomControl.class));
assertThat(cameraInfoInternal.isFlashAvailable().getValue().booleanValue()).isEqualTo(
CAMERA1_FLASH_INFO_BOOLEAN);
}
// zoom related tests just ensure it uses ZoomControl to get the value
// Full tests are performed at ZoomControlTest / ZoomControlRoboTest.
@Test
public void cameraInfo_getZoomRatio_valueIsCorrect() throws CameraInfoUnavailableException {
ZoomControl zoomControl = mock(ZoomControl.class);
CameraInfoInternal cameraInfo = new Camera2CameraInfo(mCameraManager, CAMERA0_ID,
zoomControl);
when(zoomControl.getZoomRatio()).thenReturn(new MutableLiveData<>(3.0f));
assertThat(cameraInfo.getZoomRatio().getValue()).isEqualTo(3.0f);
}
@Test
public void cameraInfo_getZoomPercentage_valueIsCorrect()
throws CameraInfoUnavailableException {
ZoomControl zoomControl = mock(ZoomControl.class);
CameraInfoInternal cameraInfo = new Camera2CameraInfo(mCameraManager, CAMERA0_ID,
zoomControl);
when(zoomControl.getZoomPercentage()).thenReturn(new MutableLiveData<>(0.2f));
assertThat(cameraInfo.getZoomPercentage().getValue()).isEqualTo(0.2f);
}
@Test
public void cameraInfo_getMaxZoomRatio_valueIsCorrect() throws CameraInfoUnavailableException {
ZoomControl zoomControl = mock(ZoomControl.class);
CameraInfoInternal cameraInfo = new Camera2CameraInfo(mCameraManager, CAMERA0_ID,
zoomControl);
when(zoomControl.getMaxZoomRatio()).thenReturn(new MutableLiveData<>(8.0f));
assertThat(cameraInfo.getMaxZoomRatio().getValue()).isEqualTo(8.0f);
}
@Test
public void cameraInfo_getMinZoomRatio_valueIsCorrect() throws CameraInfoUnavailableException {
ZoomControl zoomControl = mock(ZoomControl.class);
CameraInfoInternal cameraInfo = new Camera2CameraInfo(mCameraManager, CAMERA0_ID,
zoomControl);
when(zoomControl.getMinZoomRatio()).thenReturn(new MutableLiveData<>(1.0f));
assertThat(cameraInfo.getMinZoomRatio().getValue()).isEqualTo(1.0f);
}
private void initCameras() {
// **** Camera 0 characteristics ****//
CameraCharacteristics characteristics0 =
ShadowCameraCharacteristics.newCameraCharacteristics();
ShadowCameraCharacteristics shadowCharacteristics0 = Shadow.extract(characteristics0);
shadowCharacteristics0.set(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL,
FAKE_SUPPORTED_HARDWARE_LEVEL);
// Add a lens facing to the camera
shadowCharacteristics0.set(CameraCharacteristics.LENS_FACING, CAMERA0_LENS_FACING_INT);
// Mock the sensor orientation
shadowCharacteristics0.set(
CameraCharacteristics.SENSOR_ORIENTATION, CAMERA0_SENSOR_ORIENTATION);
// Mock the flash unit availability
shadowCharacteristics0.set(
CameraCharacteristics.FLASH_INFO_AVAILABLE, CAMERA0_FLASH_INFO_BOOLEAN);
// Add the camera to the camera service
((ShadowCameraManager)
Shadow.extract(
ApplicationProvider.getApplicationContext()
.getSystemService(Context.CAMERA_SERVICE)))
.addCamera(CAMERA0_ID, characteristics0);
// **** Camera 1 characteristics ****//
CameraCharacteristics characteristics1 =
ShadowCameraCharacteristics.newCameraCharacteristics();
ShadowCameraCharacteristics shadowCharacteristics1 = Shadow.extract(characteristics1);
shadowCharacteristics1.set(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL,
FAKE_SUPPORTED_HARDWARE_LEVEL);
// Add a lens facing to the camera
shadowCharacteristics1.set(CameraCharacteristics.LENS_FACING, CAMERA1_LENS_FACING_INT);
// Mock the sensor orientation
shadowCharacteristics1.set(
CameraCharacteristics.SENSOR_ORIENTATION, CAMERA1_SENSOR_ORIENTATION);
// Mock the flash unit availability
shadowCharacteristics1.set(
CameraCharacteristics.FLASH_INFO_AVAILABLE, CAMERA1_FLASH_INFO_BOOLEAN);
// Add the camera to the camera service
((ShadowCameraManager)
Shadow.extract(
ApplicationProvider.getApplicationContext()
.getSystemService(Context.CAMERA_SERVICE)))
.addCamera(CAMERA1_ID, characteristics1);
}
}