camera2: Implement most of CameraCaptureSession
Bug: 14964443
Change-Id: I8203842c77a94a3a6e5f89494fce658b00a4160d
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index 9a4c531..e9d4b0f 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -62,6 +62,7 @@
private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks();
private final StateListener mDeviceListener;
+ private volatile StateListener mSessionStateListener;
private final Handler mDeviceHandler;
private boolean mIdle = true;
@@ -90,6 +91,8 @@
*/
private final FrameNumberTracker mFrameNumberTracker = new FrameNumberTracker();
+ private CameraCaptureSessionImpl mCurrentSession;
+
// Runnables for all state transitions, except error, which needs the
// error code argument
@@ -98,6 +101,10 @@
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onOpened(CameraDevice.this);
+ StateListener sessionListener = mSessionStateListener;
+ if (sessionListener != null) {
+ sessionListener.onOpened(CameraDevice.this);
+ }
}
}
};
@@ -107,6 +114,10 @@
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onUnconfigured(CameraDevice.this);
+ StateListener sessionListener = mSessionStateListener;
+ if (sessionListener != null) {
+ sessionListener.onUnconfigured(CameraDevice.this);
+ }
}
}
};
@@ -116,6 +127,10 @@
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onActive(CameraDevice.this);
+ StateListener sessionListener = mSessionStateListener;
+ if (sessionListener != null) {
+ sessionListener.onActive(CameraDevice.this);
+ }
}
}
};
@@ -125,6 +140,10 @@
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onBusy(CameraDevice.this);
+ StateListener sessionListener = mSessionStateListener;
+ if (sessionListener != null) {
+ sessionListener.onBusy(CameraDevice.this);
+ }
}
}
};
@@ -133,6 +152,10 @@
@Override
public void run() {
mDeviceListener.onClosed(CameraDevice.this);
+ StateListener sessionListener = mSessionStateListener;
+ if (sessionListener != null) {
+ sessionListener.onClosed(CameraDevice.this);
+ }
}
};
@@ -141,6 +164,10 @@
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onIdle(CameraDevice.this);
+ StateListener sessionListener = mSessionStateListener;
+ if (sessionListener != null) {
+ sessionListener.onIdle(CameraDevice.this);
+ }
}
}
};
@@ -150,6 +177,10 @@
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onDisconnected(CameraDevice.this);
+ StateListener sessionListener = mSessionStateListener;
+ if (sessionListener != null) {
+ sessionListener.onDisconnected(CameraDevice.this);
+ }
}
}
};
@@ -170,7 +201,6 @@
tag = tag.substring(0, MAX_TAG_LEN);
}
TAG = tag;
-
DEBUG = Log.isLoggable(TAG, Log.DEBUG);
}
@@ -263,7 +293,43 @@
public void createCaptureSession(List<Surface> outputs,
CameraCaptureSession.StateListener listener, Handler handler)
throws CameraAccessException {
- // TODO
+ synchronized (mLock) {
+ if (DEBUG) {
+ Log.d(TAG, "createCaptureSession");
+ }
+
+ checkIfCameraClosed();
+
+ // TODO: we must be in UNCONFIGURED mode to begin with, or using another session
+
+ // TODO: dont block for this
+ boolean configureSuccess = true;
+ CameraAccessException pendingException = null;
+ try {
+ configureOutputs(outputs); // and then block until IDLE
+ } catch (CameraAccessException e) {
+ configureSuccess = false;
+ pendingException = e;
+ }
+
+ // Fire onConfigured if configureOutputs succeeded, fire onConfigureFailed otherwise.
+ CameraCaptureSessionImpl newSession =
+ new CameraCaptureSessionImpl(outputs, listener, handler, this, mDeviceHandler,
+ configureSuccess);
+
+ if (mCurrentSession != null) {
+ mCurrentSession.replaceSessionClose(newSession);
+ }
+
+ // TODO: wait until current session closes, then create the new session
+ mCurrentSession = newSession;
+
+ if (pendingException != null) {
+ throw pendingException;
+ }
+
+ mSessionStateListener = mCurrentSession.getDeviceStateListener();
+ }
}
@Override
@@ -275,7 +341,7 @@
CameraMetadataNative templatedRequest = new CameraMetadataNative();
try {
- mRemoteDevice.createDefaultRequest(templateType, /* out */templatedRequest);
+ mRemoteDevice.createDefaultRequest(templateType, /*out*/templatedRequest);
} catch (CameraRuntimeException e) {
throw e.asChecked();
} catch (RemoteException e) {
@@ -304,10 +370,8 @@
@Override
public int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException {
- // TODO: remove this. Throw IAE if the request is null or empty. Need to update API doc.
- if (requests.isEmpty()) {
- Log.w(TAG, "Capture burst request list is empty, do nothing!");
- return -1;
+ if (requests == null || requests.isEmpty()) {
+ throw new IllegalArgumentException("At least one request must be given");
}
return submitCaptureRequest(requests, listener, handler, /*streaming*/false);
}
@@ -454,10 +518,8 @@
@Override
public int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException {
- // TODO: remove this. Throw IAE if the request is null or empty. Need to update API doc.
- if (requests.isEmpty()) {
- Log.w(TAG, "Set Repeating burst request list is empty, do nothing!");
- return -1;
+ if (requests == null || requests.isEmpty()) {
+ throw new IllegalArgumentException("At least one request must be given");
}
return submitCaptureRequest(requests, listener, handler, /*streaming*/true);
}
@@ -951,10 +1013,14 @@
}
/**
- * Default handler management. If handler is null, get the current thread's
- * Looper to create a Handler with. If no looper exists, throw exception.
+ * Default handler management.
+ *
+ * <p>
+ * If handler is null, get the current thread's
+ * Looper to create a Handler with. If no looper exists, throw {@code IllegalArgumentException}.
+ * </p>
*/
- private Handler checkHandler(Handler handler) {
+ static Handler checkHandler(Handler handler) {
if (handler == null) {
Looper looper = Looper.myLooper();
if (looper == null) {