am ad45fa64: Merge "Camera2: Fire all callbacks" into klp-dev
* commit 'ad45fa64382fa00778ff8ddfd1ac65d81fd55404': Camera2: Fire all callbacks
This commit is contained in:
@@ -197,26 +197,33 @@ public interface CameraDevice extends AutoCloseable {
|
||||
* if the format is user-visible, it must be one of android.scaler.availableFormats;
|
||||
* and the size must be one of android.scaler.available[Processed|Jpeg]Sizes).</p>
|
||||
*
|
||||
* <p>To change the output, the camera device must be idle. The device is considered
|
||||
* to be idle once all in-flight and pending capture requests have been processed,
|
||||
* and all output image buffers from the captures have been sent to their destination
|
||||
* Surfaces.</p>
|
||||
* <p>When this method is called with valid Surfaces, the device will transition to the {@link
|
||||
* StateListener#onBusy busy state}. Once configuration is complete, the device will transition
|
||||
* into the {@link StateListener#onIdle idle state}. Capture requests using the newly-configured
|
||||
* Surfaces may then be submitted with {@link #capture}, {@link #captureBurst}, {@link
|
||||
* #setRepeatingRequest}, or {@link #setRepeatingBurst}.</p>
|
||||
*
|
||||
* <p>To reach an idle state without cancelling any submitted captures, first
|
||||
* stop any repeating request/burst with {@link #stopRepeating}, and then
|
||||
* wait for the {@link StateListener#onIdle} callback to be
|
||||
* called. To idle as fast as possible, use {@link #flush} and wait for the
|
||||
* idle callback.</p>
|
||||
* <p>If this method is called while the camera device is still actively processing previously
|
||||
* submitted captures, then the following sequence of events occurs: The device transitions to
|
||||
* the busy state and calls the {@link StateListener#onBusy} callback. Second, if a repeating
|
||||
* request is set it is cleared. Third, the device finishes up all in-flight and pending
|
||||
* requests. Finally, once the device is idle, it then reconfigures its outputs, and calls the
|
||||
* {@link StateListener#onIdle} method once it is again ready to accept capture
|
||||
* requests. Therefore, no submitted work is discarded. To idle as fast as possible, use {@link
|
||||
* #flush} and wait for the idle callback before calling configureOutputs. This will discard
|
||||
* work, but reaches the new configuration sooner.</p>
|
||||
*
|
||||
* <p>Using larger resolution outputs, or more outputs, can result in slower
|
||||
* output rate from the device.</p>
|
||||
*
|
||||
* <p>Configuring the outputs with an empty or null list will transition
|
||||
* the camera into an {@link StateListener#onUnconfigured unconfigured state}.
|
||||
* </p>
|
||||
* <p>Configuring the outputs with an empty or null list will transition the camera into an
|
||||
* {@link StateListener#onUnconfigured unconfigured state} instead of the {@link
|
||||
* StateListener#onIdle idle state}. </p>
|
||||
*
|
||||
* <p>Calling configureOutputs with the same arguments as the last call to
|
||||
* configureOutputs has no effect.</p>
|
||||
* configureOutputs has no effect, and the {@link StateListener#onBusy busy}
|
||||
* and {@link StateListener#onIdle idle} state transitions will happen
|
||||
* immediately.</p>
|
||||
*
|
||||
* @param outputs The new set of Surfaces that should be made available as
|
||||
* targets for captured image data.
|
||||
@@ -228,7 +235,10 @@ public interface CameraDevice extends AutoCloseable {
|
||||
* @throws IllegalStateException if the camera device is not idle, or
|
||||
* if the camera device has been closed
|
||||
*
|
||||
* @see StateListener#onBusy
|
||||
* @see StateListener#onIdle
|
||||
* @see StateListener#onActive
|
||||
* @see StateListener#onUnconfigured
|
||||
* @see #stopRepeating
|
||||
* @see #flush
|
||||
*/
|
||||
@@ -515,31 +525,6 @@ public interface CameraDevice extends AutoCloseable {
|
||||
*/
|
||||
public void waitUntilIdle() throws CameraAccessException;
|
||||
|
||||
/**
|
||||
* Set the listener object to call when an asynchronous device event occurs,
|
||||
* such as errors or idle notifications.
|
||||
*
|
||||
* <p>The events reported here are device-wide; notifications about
|
||||
* individual capture requests or capture results are reported through
|
||||
* {@link CaptureListener}.</p>
|
||||
*
|
||||
* <p>If the camera device is idle when the listener is set, then the
|
||||
* {@link StateListener#onIdle} method will be immediately called,
|
||||
* even if the device has never been active before.
|
||||
* </p>
|
||||
*
|
||||
* @param listener the CameraDeviceListener to send device-level event
|
||||
* notifications to. Setting this to null will stop notifications.
|
||||
* @param handler the handler on which the listener should be invoked, or
|
||||
* {@code null} to use the current thread's {@link android.os.Looper looper}.
|
||||
*
|
||||
* @throws IllegalArgumentException if handler is null, the listener is
|
||||
* not null, and the calling thread has no looper
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void setDeviceListener(StateListener listener, Handler handler);
|
||||
|
||||
/**
|
||||
* Flush all captures currently pending and in-progress as fast as
|
||||
* possible.
|
||||
@@ -577,13 +562,24 @@ public interface CameraDevice extends AutoCloseable {
|
||||
public void flush() throws CameraAccessException;
|
||||
|
||||
/**
|
||||
* Close the connection to this camera device. After this call, all calls to
|
||||
* Close the connection to this camera device.
|
||||
*
|
||||
* <p>After this call, all calls to
|
||||
* the camera device interface will throw a {@link IllegalStateException},
|
||||
* except for calls to close().
|
||||
* except for calls to close(). Once the device has fully shut down, the
|
||||
* {@link StateListener#onClosed} callback will be called, and the camera is
|
||||
* free to be re-opened.</p>
|
||||
*
|
||||
* <p>After this call, besides the final {@link StateListener#onClosed} call, no calls to the
|
||||
* device's {@link StateListener} will occur, and any remaining submitted capture requests will
|
||||
* not fire their {@link CaptureListener} callbacks.</p>
|
||||
*
|
||||
* <p>To shut down as fast as possible, call the {@link #flush} method and then {@link #close}
|
||||
* once the flush completes. This will discard some capture requests, but results in faster
|
||||
* shutdown.</p>
|
||||
*/
|
||||
@Override
|
||||
public void close();
|
||||
// TODO: We should decide on the behavior of in-flight requests should be on close.
|
||||
|
||||
/**
|
||||
* <p>A listener for tracking the progress of a {@link CaptureRequest}
|
||||
@@ -713,6 +709,9 @@ public interface CameraDevice extends AutoCloseable {
|
||||
* A listener for notifications about the state of a camera
|
||||
* device.
|
||||
*
|
||||
* <p>A listener must be provided to the {@link CameraManager#openCamera}
|
||||
* method to open a camera device.</p>
|
||||
*
|
||||
* <p>These events include notifications about the device becoming idle (
|
||||
* allowing for {@link #configureOutputs} to be called), about device
|
||||
* disconnection, and about unexpected device errors.</p>
|
||||
@@ -722,7 +721,7 @@ public interface CameraDevice extends AutoCloseable {
|
||||
* the {@link #capture}, {@link #captureBurst}, {@link
|
||||
* #setRepeatingRequest}, or {@link #setRepeatingBurst} methods.
|
||||
*
|
||||
* @see #setDeviceListener
|
||||
* @see CameraManager#openCamera
|
||||
*/
|
||||
public static abstract class StateListener {
|
||||
/**
|
||||
|
||||
@@ -197,6 +197,8 @@ public final class CameraManager {
|
||||
* {@link #openCamera}.
|
||||
*
|
||||
* @param cameraId The unique identifier of the camera device to open
|
||||
* @param listener The listener for the camera. Must not be null.
|
||||
* @param handler The handler to call the listener on. Must not be null.
|
||||
*
|
||||
* @throws CameraAccessException if the camera is disabled by device policy,
|
||||
* or too many camera devices are already open, or the cameraId does not match
|
||||
@@ -204,11 +206,14 @@ public final class CameraManager {
|
||||
*
|
||||
* @throws SecurityException if the application does not have permission to
|
||||
* access the camera
|
||||
* @throws IllegalArgumentException if listener or handler is null.
|
||||
*
|
||||
* @see #getCameraIdList
|
||||
* @see android.app.admin.DevicePolicyManager#setCameraDisabled
|
||||
*/
|
||||
private CameraDevice openCamera(String cameraId) throws CameraAccessException {
|
||||
private void openCameraDeviceUserAsync(String cameraId,
|
||||
CameraDevice.StateListener listener, Handler handler)
|
||||
throws CameraAccessException {
|
||||
try {
|
||||
|
||||
synchronized (mLock) {
|
||||
@@ -216,7 +221,10 @@ public final class CameraManager {
|
||||
ICameraDeviceUser cameraUser;
|
||||
|
||||
android.hardware.camera2.impl.CameraDevice device =
|
||||
new android.hardware.camera2.impl.CameraDevice(cameraId);
|
||||
new android.hardware.camera2.impl.CameraDevice(
|
||||
cameraId,
|
||||
listener,
|
||||
handler);
|
||||
|
||||
BinderHolder holder = new BinderHolder();
|
||||
mCameraService.connectDevice(device.getCallbacks(),
|
||||
@@ -225,10 +233,9 @@ public final class CameraManager {
|
||||
cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
|
||||
|
||||
// TODO: factor out listener to be non-nested, then move setter to constructor
|
||||
// For now, calling setRemoteDevice will fire initial
|
||||
// onOpened/onUnconfigured callbacks.
|
||||
device.setRemoteDevice(cameraUser);
|
||||
|
||||
return device;
|
||||
|
||||
}
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
@@ -238,7 +245,6 @@ public final class CameraManager {
|
||||
throw e.asChecked();
|
||||
} catch (RemoteException e) {
|
||||
// impossible
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,16 +309,7 @@ public final class CameraManager {
|
||||
}
|
||||
}
|
||||
|
||||
final CameraDevice camera = openCamera(cameraId);
|
||||
camera.setDeviceListener(listener, handler);
|
||||
|
||||
// TODO: make truly async in the camera service
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onOpened(camera);
|
||||
}
|
||||
});
|
||||
openCameraDeviceUserAsync(cameraId, listener, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -55,8 +55,10 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
private final Object mLock = new Object();
|
||||
private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks();
|
||||
|
||||
private StateListener mDeviceListener;
|
||||
private Handler mDeviceHandler;
|
||||
private final StateListener mDeviceListener;
|
||||
private final Handler mDeviceHandler;
|
||||
|
||||
private boolean mIdle = true;
|
||||
|
||||
private final SparseArray<CaptureListenerHolder> mCaptureListenerMap =
|
||||
new SparseArray<CaptureListenerHolder>();
|
||||
@@ -67,8 +69,72 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
|
||||
private final String mCameraId;
|
||||
|
||||
public CameraDevice(String cameraId) {
|
||||
// Runnables for all state transitions, except error, which needs the
|
||||
// error code argument
|
||||
|
||||
private final Runnable mCallOnOpened = new Runnable() {
|
||||
public void run() {
|
||||
if (!CameraDevice.this.isClosed()) {
|
||||
mDeviceListener.onOpened(CameraDevice.this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mCallOnUnconfigured = new Runnable() {
|
||||
public void run() {
|
||||
if (!CameraDevice.this.isClosed()) {
|
||||
mDeviceListener.onUnconfigured(CameraDevice.this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mCallOnActive = new Runnable() {
|
||||
public void run() {
|
||||
if (!CameraDevice.this.isClosed()) {
|
||||
mDeviceListener.onActive(CameraDevice.this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mCallOnBusy = new Runnable() {
|
||||
public void run() {
|
||||
if (!CameraDevice.this.isClosed()) {
|
||||
mDeviceListener.onBusy(CameraDevice.this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mCallOnClosed = new Runnable() {
|
||||
public void run() {
|
||||
if (!CameraDevice.this.isClosed()) {
|
||||
mDeviceListener.onClosed(CameraDevice.this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mCallOnIdle = new Runnable() {
|
||||
public void run() {
|
||||
if (!CameraDevice.this.isClosed()) {
|
||||
mDeviceListener.onIdle(CameraDevice.this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mCallOnDisconnected = new Runnable() {
|
||||
public void run() {
|
||||
if (!CameraDevice.this.isClosed()) {
|
||||
mDeviceListener.onDisconnected(CameraDevice.this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public CameraDevice(String cameraId, StateListener listener, Handler handler) {
|
||||
if (cameraId == null || listener == null || handler == null) {
|
||||
throw new IllegalArgumentException("Null argument given");
|
||||
}
|
||||
mCameraId = cameraId;
|
||||
mDeviceListener = listener;
|
||||
mDeviceHandler = handler;
|
||||
TAG = String.format("CameraDevice-%s-JV", mCameraId);
|
||||
DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
}
|
||||
@@ -79,7 +145,12 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
|
||||
public void setRemoteDevice(ICameraDeviceUser remoteDevice) {
|
||||
// TODO: Move from decorator to direct binder-mediated exceptions
|
||||
mRemoteDevice = CameraBinderDecorator.newInstance(remoteDevice);
|
||||
synchronized(mLock) {
|
||||
mRemoteDevice = CameraBinderDecorator.newInstance(remoteDevice);
|
||||
|
||||
mDeviceHandler.post(mCallOnOpened);
|
||||
mDeviceHandler.post(mCallOnUnconfigured);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,7 +160,13 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
|
||||
@Override
|
||||
public void configureOutputs(List<Surface> outputs) throws CameraAccessException {
|
||||
// Treat a null input the same an empty list
|
||||
if (outputs == null) {
|
||||
outputs = new ArrayList<Surface>();
|
||||
}
|
||||
synchronized (mLock) {
|
||||
checkIfCameraClosed();
|
||||
|
||||
HashSet<Surface> addSet = new HashSet<Surface>(outputs); // Streams to create
|
||||
List<Integer> deleteList = new ArrayList<Integer>(); // Streams to delete
|
||||
|
||||
@@ -105,9 +182,13 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// TODO: mRemoteDevice.beginConfigure
|
||||
mDeviceHandler.post(mCallOnBusy);
|
||||
stopRepeating();
|
||||
|
||||
try {
|
||||
mRemoteDevice.waitUntilIdle();
|
||||
|
||||
// TODO: mRemoteDevice.beginConfigure
|
||||
// Delete all streams first (to free up HW resources)
|
||||
for (Integer streamId : deleteList) {
|
||||
mRemoteDevice.deleteStream(streamId);
|
||||
@@ -126,7 +207,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
} catch (CameraRuntimeException e) {
|
||||
if (e.getReason() == CAMERA_IN_USE) {
|
||||
throw new IllegalStateException("The camera is currently busy." +
|
||||
" You must call waitUntilIdle before trying to reconfigure.");
|
||||
" You must wait until the previous operation completes.");
|
||||
}
|
||||
|
||||
throw e.asChecked();
|
||||
@@ -134,6 +215,12 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
// impossible
|
||||
return;
|
||||
}
|
||||
|
||||
if (outputs.size() > 0) {
|
||||
mDeviceHandler.post(mCallOnIdle);
|
||||
} else {
|
||||
mDeviceHandler.post(mCallOnUnconfigured);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,6 +228,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
public CaptureRequest.Builder createCaptureRequest(int templateType)
|
||||
throws CameraAccessException {
|
||||
synchronized (mLock) {
|
||||
checkIfCameraClosed();
|
||||
|
||||
CameraMetadataNative templatedRequest = new CameraMetadataNative();
|
||||
|
||||
@@ -188,7 +276,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
|
||||
checkIfCameraClosed();
|
||||
int requestId;
|
||||
|
||||
try {
|
||||
@@ -208,6 +296,11 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
mRepeatingRequestIdStack.add(requestId);
|
||||
}
|
||||
|
||||
if (mIdle) {
|
||||
mDeviceHandler.post(mCallOnActive);
|
||||
}
|
||||
mIdle = false;
|
||||
|
||||
return requestId;
|
||||
}
|
||||
}
|
||||
@@ -233,7 +326,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
public void stopRepeating() throws CameraAccessException {
|
||||
|
||||
synchronized (mLock) {
|
||||
|
||||
checkIfCameraClosed();
|
||||
while (!mRepeatingRequestIdStack.isEmpty()) {
|
||||
int requestId = mRepeatingRequestIdStack.pop();
|
||||
|
||||
@@ -269,21 +362,12 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDeviceListener(StateListener listener, Handler handler) {
|
||||
synchronized (mLock) {
|
||||
if (listener != null) {
|
||||
handler = checkHandler(handler);
|
||||
}
|
||||
|
||||
mDeviceListener = listener;
|
||||
mDeviceHandler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws CameraAccessException {
|
||||
synchronized (mLock) {
|
||||
checkIfCameraClosed();
|
||||
|
||||
mDeviceHandler.post(mCallOnBusy);
|
||||
try {
|
||||
mRemoteDevice.flush();
|
||||
} catch (CameraRuntimeException e) {
|
||||
@@ -297,9 +381,6 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
// TODO: every method should throw IllegalStateException after close has been called
|
||||
|
||||
synchronized (mLock) {
|
||||
|
||||
try {
|
||||
@@ -312,8 +393,11 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
// impossible
|
||||
}
|
||||
|
||||
mRemoteDevice = null;
|
||||
if (mRemoteDevice != null) {
|
||||
mDeviceHandler.post(mCallOnClosed);
|
||||
}
|
||||
|
||||
mRemoteDevice = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,49 +483,44 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
|
||||
@Override
|
||||
public void onCameraError(final int errorCode) {
|
||||
synchronized (mLock) {
|
||||
if (CameraDevice.this.mDeviceListener == null) return;
|
||||
final StateListener listener = CameraDevice.this.mDeviceListener;
|
||||
Runnable r = null;
|
||||
Runnable r = null;
|
||||
if (isClosed()) return;
|
||||
|
||||
synchronized(mLock) {
|
||||
switch (errorCode) {
|
||||
case ERROR_CAMERA_DISCONNECTED:
|
||||
r = new Runnable() {
|
||||
public void run() {
|
||||
listener.onDisconnected(CameraDevice.this);
|
||||
}
|
||||
};
|
||||
r = mCallOnDisconnected;
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Unknown error from camera device: " + errorCode);
|
||||
// no break
|
||||
case ERROR_CAMERA_DEVICE:
|
||||
case ERROR_CAMERA_SERVICE:
|
||||
r = new Runnable() {
|
||||
public void run() {
|
||||
listener.onError(CameraDevice.this, errorCode);
|
||||
if (!CameraDevice.this.isClosed()) {
|
||||
mDeviceListener.onError(CameraDevice.this, errorCode);
|
||||
}
|
||||
}
|
||||
};
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Unknown error from camera device: " + errorCode);
|
||||
}
|
||||
if (r != null) {
|
||||
CameraDevice.this.mDeviceHandler.post(r);
|
||||
}
|
||||
CameraDevice.this.mDeviceHandler.post(r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCameraIdle() {
|
||||
if (isClosed()) return;
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Camera now idle");
|
||||
}
|
||||
synchronized (mLock) {
|
||||
if (CameraDevice.this.mDeviceListener == null) return;
|
||||
final StateListener listener = CameraDevice.this.mDeviceListener;
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
listener.onIdle(CameraDevice.this);
|
||||
}
|
||||
};
|
||||
CameraDevice.this.mDeviceHandler.post(r);
|
||||
if (!CameraDevice.this.mIdle) {
|
||||
CameraDevice.this.mDeviceHandler.post(mCallOnIdle);
|
||||
}
|
||||
CameraDevice.this.mIdle = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,14 +540,18 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isClosed()) return;
|
||||
|
||||
// Dispatch capture start notice
|
||||
holder.getHandler().post(
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
holder.getListener().onCaptureStarted(
|
||||
CameraDevice.this,
|
||||
holder.getRequest(),
|
||||
timestamp);
|
||||
if (!CameraDevice.this.isClosed()) {
|
||||
holder.getListener().onCaptureStarted(
|
||||
CameraDevice.this,
|
||||
holder.getRequest(),
|
||||
timestamp);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -503,6 +586,8 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isClosed()) return;
|
||||
|
||||
final CaptureRequest request = holder.getRequest();
|
||||
final CaptureResult resultAsCapture = new CaptureResult(result, request, requestId);
|
||||
|
||||
@@ -510,10 +595,12 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
holder.getListener().onCaptureCompleted(
|
||||
CameraDevice.this,
|
||||
request,
|
||||
resultAsCapture);
|
||||
if (!CameraDevice.this.isClosed()){
|
||||
holder.getListener().onCaptureCompleted(
|
||||
CameraDevice.this,
|
||||
request,
|
||||
resultAsCapture);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -541,4 +628,10 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
|
||||
throw new IllegalStateException("CameraDevice was already closed");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isClosed() {
|
||||
synchronized(mLock) {
|
||||
return (mRemoteDevice == null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user