This source file includes following definitions.
- wasDisconnected
- wasError
- getCode
- openCamera
- assertEquals
- assertInitialState
- onOpened
- onDisconnected
- onError
- onClosed
- blockUntilOpen
package com.android.ex.camera2.blocking;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
import java.util.Objects;
public class BlockingCameraManager {
private static final String TAG = "BlockingCameraManager";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
private static final int OPEN_TIME_OUT_MS = 2000;
public static class BlockingOpenException extends Exception {
private static final long serialVersionUID = 12397123891238912L;
public static final int ERROR_DISCONNECTED = 0;
private final int mError;
public boolean wasDisconnected() {
return mError == ERROR_DISCONNECTED;
}
public boolean wasError() {
return mError != ERROR_DISCONNECTED;
}
public int getCode() {
return mError;
}
public BlockingOpenException(int errorCode, String message) {
super(message);
mError = errorCode;
}
}
private final CameraManager mManager;
public BlockingCameraManager(CameraManager manager) {
if (manager == null) {
throw new IllegalArgumentException("manager must not be null");
}
mManager = manager;
}
public CameraDevice openCamera(String cameraId, CameraDevice.StateCallback listener,
Handler handler) throws CameraAccessException, BlockingOpenException {
if (handler == null) {
throw new IllegalArgumentException("handler must not be null");
} else if (handler.getLooper() == Looper.myLooper()) {
throw new IllegalArgumentException("handler's looper must not be the current looper");
}
return (new OpenListener(mManager, cameraId, listener, handler)).blockUntilOpen();
}
private static void assertEquals(Object a, Object b) {
if (!Objects.equals(a, b)) {
throw new AssertionError("Expected " + a + ", but got " + b);
}
}
private class OpenListener extends CameraDevice.StateCallback {
private static final int ERROR_UNINITIALIZED = -1;
private final String mCameraId;
private final CameraDevice.StateCallback mProxy;
private final Object mLock = new Object();
private final ConditionVariable mDeviceReady = new ConditionVariable();
private CameraDevice mDevice = null;
private boolean mSuccess = false;
private int mError = ERROR_UNINITIALIZED;
private boolean mDisconnected = false;
private boolean mNoReply = true;
private boolean mTimedOut = false;
OpenListener(CameraManager manager, String cameraId,
CameraDevice.StateCallback listener, Handler handler)
throws CameraAccessException {
mCameraId = cameraId;
mProxy = listener;
manager.openCamera(cameraId, this, handler);
}
private void assertInitialState() {
assertEquals(null, mDevice);
assertEquals(false, mDisconnected);
assertEquals(ERROR_UNINITIALIZED, mError);
assertEquals(false, mSuccess);
}
@Override
public void onOpened(CameraDevice camera) {
if (VERBOSE) {
Log.v(TAG, "onOpened: camera " + ((camera != null) ? camera.getId() : "null"));
}
synchronized (mLock) {
assertInitialState();
mNoReply = false;
mSuccess = true;
mDevice = camera;
mDeviceReady.open();
if (mTimedOut && camera != null) {
camera.close();
return;
}
}
if (mProxy != null) mProxy.onOpened(camera);
}
@Override
public void onDisconnected(CameraDevice camera) {
if (VERBOSE) {
Log.v(TAG, "onDisconnected: camera "
+ ((camera != null) ? camera.getId() : "null"));
}
synchronized (mLock) {
assertInitialState();
mNoReply = false;
mDisconnected = true;
mDevice = camera;
mDeviceReady.open();
if (mTimedOut && camera != null) {
camera.close();
return;
}
}
if (mProxy != null) mProxy.onDisconnected(camera);
}
@Override
public void onError(CameraDevice camera, int error) {
if (VERBOSE) {
Log.v(TAG, "onError: camera " + ((camera != null) ? camera.getId() : "null"));
}
if (error <= 0) {
throw new AssertionError("Expected error to be a positive number");
}
synchronized (mLock) {
mNoReply = false;
mError = error;
mDevice = camera;
mDeviceReady.open();
if (mTimedOut && camera != null) {
camera.close();
return;
}
}
if (mProxy != null) mProxy.onError(camera, error);
}
@Override
public void onClosed(CameraDevice camera) {
if (mProxy != null) mProxy.onClosed(camera);
}
CameraDevice blockUntilOpen() throws BlockingOpenException {
if (!mDeviceReady.block(OPEN_TIME_OUT_MS)) {
synchronized (mLock) {
if (mNoReply) {
mTimedOut = true;
throw new TimeoutRuntimeException(String.format(
"Timed out after %d ms while trying to open camera device %s",
OPEN_TIME_OUT_MS, mCameraId));
}
}
}
synchronized (mLock) {
if (!mSuccess && mDevice != null) {
mDevice.close();
}
if (mSuccess) {
return mDevice;
} else {
if (mDisconnected) {
throw new BlockingOpenException(
BlockingOpenException.ERROR_DISCONNECTED,
"Failed to open camera device: it is disconnected");
} else if (mError != ERROR_UNINITIALIZED) {
throw new BlockingOpenException(
mError,
"Failed to open camera device: error code " + mError);
} else {
throw new AssertionError("Failed to open camera device (impl bug)");
}
}
}
}
}
}