[go: nahoru, domu]

blob: bc553f991c2389369a43aa73f27a81a48568f8af [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.internal.compat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import android.Manifest;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Size;
import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.camera.camera2.internal.compat.params.OutputConfigurationCompat;
import androidx.camera.camera2.internal.compat.params.SessionConfigurationCompat;
import androidx.core.os.HandlerCompat;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.MediumTest;
import androidx.test.rule.GrantPermissionRule;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Collections;
import java.util.concurrent.Semaphore;
/**
* Tests some of the methods of {@link CameraDeviceCompat} on device.
*
* <p>These need to run on device since they rely on native implementation details of the
* {@link CameraDevice} class on some API levels.
*/
@MediumTest
@RunWith(AndroidJUnit4.class)
public final class CameraDeviceCompatDeviceTest {
private final Semaphore mOpenCloseSemaphore = new Semaphore(0);
@Rule
public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
Manifest.permission.CAMERA);
private CameraDevice mCameraDevice;
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
mCameraDevice = camera;
mOpenCloseSemaphore.release();
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
mCameraDevice = camera;
mOpenCloseSemaphore.release();
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
mCameraDevice = camera;
mOpenCloseSemaphore.release();
}
@Override
public void onClosed(@NonNull CameraDevice camera) {
mCameraDevice = null;
mOpenCloseSemaphore.release();
}
};
private SurfaceTexture mSurfaceTexture;
private Surface mSurface;
private HandlerThread mCompatHandlerThread;
private Handler mCompatHandler;
@Before
public void setUp() throws CameraAccessException, InterruptedException {
CameraManager cameraManager =
(CameraManager) ApplicationProvider.getApplicationContext().getSystemService(
Context.CAMERA_SERVICE);
String[] cameraIds = cameraManager.getCameraIdList();
Assume.assumeTrue("No cameras found on device.", cameraIds.length > 0);
String cameraId = cameraIds[0];
mCompatHandlerThread = new HandlerThread("DispatchThread");
mCompatHandlerThread.start();
mCompatHandler = HandlerCompat.createAsync(mCompatHandlerThread.getLooper());
cameraManager.openCamera(cameraId, mStateCallback, mCompatHandler);
mOpenCloseSemaphore.acquire();
if (mCameraDevice == null) {
throw new AssertionError("Unable to open camera.");
}
StreamConfigurationMap streamConfigurationMap = cameraManager.getCameraCharacteristics(
cameraId).get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] validSizes = streamConfigurationMap.getOutputSizes(SurfaceTexture.class);
Assume.assumeTrue("No valid sizes available for SurfaceTexture.", validSizes.length > 0);
mSurfaceTexture = new SurfaceTexture(0);
mSurfaceTexture.setDefaultBufferSize(validSizes[0].getWidth(), validSizes[0].getHeight());
mSurface = new Surface(mSurfaceTexture);
}
@After
public void tearDown() throws InterruptedException {
if (mCameraDevice != null) {
mCameraDevice.close();
mOpenCloseSemaphore.acquire();
}
if (mSurface != null) {
mSurface.release();
}
if (mSurfaceTexture != null) {
mSurfaceTexture.release();
}
if (mCompatHandlerThread != null) {
mCompatHandlerThread.quitSafely();
}
}
@Test
@SuppressWarnings("deprecation") /* AsyncTask */
public void canConfigureCaptureSession() throws CameraAccessException {
OutputConfigurationCompat outputConfig = new OutputConfigurationCompat(mSurface);
CameraCaptureSession.StateCallback stateCallback =
mock(CameraCaptureSession.StateCallback.class);
SessionConfigurationCompat sessionConfig = new SessionConfigurationCompat(
SessionConfigurationCompat.SESSION_REGULAR,
Collections.singletonList(outputConfig), android.os.AsyncTask.THREAD_POOL_EXECUTOR,
stateCallback);
CameraDeviceCompat deviceCompat = CameraDeviceCompat.toCameraDeviceCompat(mCameraDevice,
mCompatHandler);
try {
deviceCompat.createCaptureSession(sessionConfig);
} catch (CameraAccessException e) {
// If the camera has been disconnected during the test (likely due to another process
// stealing the camera), then we will skip the test.
Assume.assumeTrue("Camera disconnected during test.",
e.getReason() != CameraAccessException.CAMERA_DISCONNECTED);
// This is not an error we expect should reasonably happen. Rethrow the exception.
throw e;
}
verify(stateCallback, timeout(3000)).onConfigured(any(CameraCaptureSession.class));
}
}