Merge "Camera2: Add buffer drop error callback" into nyc-dev
am: 95171050e9
* commit '95171050e9877deb9b1f84b4c55aa828229e2809':
Camera2: Add buffer drop error callback
diff --git a/api/current.txt b/api/current.txt
index 032b2cb..e6a5b1a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13776,6 +13776,7 @@
public static abstract class CameraCaptureSession.CaptureCallback {
ctor public CameraCaptureSession.CaptureCallback();
+ method public void onCaptureBufferLost(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.view.Surface, long);
method public void onCaptureCompleted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult);
method public void onCaptureFailed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureFailure);
method public void onCaptureProgressed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
diff --git a/api/system-current.txt b/api/system-current.txt
index 3b8f584..e70b6f6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -14177,6 +14177,7 @@
public static abstract class CameraCaptureSession.CaptureCallback {
ctor public CameraCaptureSession.CaptureCallback();
+ method public void onCaptureBufferLost(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.view.Surface, long);
method public void onCaptureCompleted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult);
method public void onCaptureFailed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureFailure);
method public void onCaptureProgressed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
diff --git a/api/test-current.txt b/api/test-current.txt
index da31235..40e1156 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -13786,6 +13786,7 @@
public static abstract class CameraCaptureSession.CaptureCallback {
ctor public CameraCaptureSession.CaptureCallback();
+ method public void onCaptureBufferLost(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.view.Surface, long);
method public void onCaptureCompleted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult);
method public void onCaptureFailed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureFailure);
method public void onCaptureProgressed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index 8724a96..38279a4 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -990,6 +990,30 @@
int sequenceId) {
// default empty implementation
}
+
+ /**
+ * <p>This method is called if a single buffer for a capture could not be sent to its
+ * destination surface.</p>
+ *
+ * <p>If the whole capture failed, then {@link #onCaptureFailed} will be called instead. If
+ * some but not all buffers were captured but the result metadata will not be available,
+ * then onCaptureFailed will be invoked with {@link CaptureFailure#wasImageCaptured}
+ * returning true, along with one or more calls to {@link #onCaptureBufferLost} for the
+ * failed outputs.</p>
+ *
+ * @param session
+ * The session returned by {@link CameraDevice#createCaptureSession}
+ * @param request
+ * The request that was given to the CameraDevice
+ * @param target
+ * The target Surface that the buffer will not be produced for
+ * @param frameNumber
+ * The frame number for the request
+ */
+ public void onCaptureBufferLost(@NonNull CameraCaptureSession session,
+ @NonNull CaptureRequest request, @NonNull Surface target, long frameNumber) {
+ // default empty implementation
+ }
}
/**
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 37d2ea2..d84a6fc 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -1116,6 +1116,11 @@
int sequenceId) {
// default empty implementation
}
+
+ public void onCaptureBufferLost(CameraDevice camera,
+ CaptureRequest request, Surface target, long frameNumber) {
+ // default empty implementation
+ }
}
/**
@@ -1887,48 +1892,66 @@
final CaptureRequest request = holder.getRequest(subsequenceId);
- // No way to report buffer errors right now
+ Runnable failureDispatch = null;
if (errorCode == ERROR_CAMERA_BUFFER) {
- Log.e(TAG, String.format("Lost output buffer reported for frame %d", frameNumber));
- return;
- }
-
- boolean mayHaveBuffers = (errorCode == ERROR_CAMERA_RESULT);
-
- // This is only approximate - exact handling needs the camera service and HAL to
- // disambiguate between request failures to due abort and due to real errors.
- // For now, assume that if the session believes we're mid-abort, then the error
- // is due to abort.
- int reason = (mCurrentSession != null && mCurrentSession.isAborting()) ?
- CaptureFailure.REASON_FLUSHED :
- CaptureFailure.REASON_ERROR;
-
- final CaptureFailure failure = new CaptureFailure(
- request,
- reason,
- /*dropped*/ mayHaveBuffers,
- requestId,
- frameNumber);
-
- Runnable failureDispatch = new Runnable() {
- @Override
- public void run() {
- if (!CameraDeviceImpl.this.isClosed()){
- holder.getCallback().onCaptureFailed(
- CameraDeviceImpl.this,
- request,
- failure);
- }
+ final Surface outputSurface =
+ mConfiguredOutputs.get(resultExtras.getErrorStreamId()).getSurface();
+ if (DEBUG) {
+ Log.v(TAG, String.format("Lost output buffer reported for frame %d, target %s",
+ frameNumber, outputSurface));
}
- };
- holder.getHandler().post(failureDispatch);
+ failureDispatch = new Runnable() {
+ @Override
+ public void run() {
+ if (!CameraDeviceImpl.this.isClosed()){
+ holder.getCallback().onCaptureBufferLost(
+ CameraDeviceImpl.this,
+ request,
+ outputSurface,
+ frameNumber);
+ }
+ }
+ };
+ } else {
+ boolean mayHaveBuffers = (errorCode == ERROR_CAMERA_RESULT);
- // Fire onCaptureSequenceCompleted if appropriate
- if (DEBUG) {
- Log.v(TAG, String.format("got error frame %d", frameNumber));
+ // This is only approximate - exact handling needs the camera service and HAL to
+ // disambiguate between request failures to due abort and due to real errors. For
+ // now, assume that if the session believes we're mid-abort, then the error is due
+ // to abort.
+ int reason = (mCurrentSession != null && mCurrentSession.isAborting()) ?
+ CaptureFailure.REASON_FLUSHED :
+ CaptureFailure.REASON_ERROR;
+
+ final CaptureFailure failure = new CaptureFailure(
+ request,
+ reason,
+ /*dropped*/ mayHaveBuffers,
+ requestId,
+ frameNumber);
+
+ failureDispatch = new Runnable() {
+ @Override
+ public void run() {
+ if (!CameraDeviceImpl.this.isClosed()){
+ holder.getCallback().onCaptureFailed(
+ CameraDeviceImpl.this,
+ request,
+ failure);
+ }
+ }
+ };
+
+ // Fire onCaptureSequenceCompleted if appropriate
+ if (DEBUG) {
+ Log.v(TAG, String.format("got error frame %d", frameNumber));
+ }
+ mFrameNumberTracker.updateTracker(frameNumber, /*error*/true, request.isReprocess());
+ checkAndFireSequenceComplete();
}
- mFrameNumberTracker.updateTracker(frameNumber, /*error*/true, request.isReprocess());
- checkAndFireSequenceComplete();
+
+ // Dispatch the failure callback
+ holder.getHandler().post(failureDispatch);
}
} // public class CameraDeviceCallbacks
diff --git a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
index d859da7..40535e2 100644
--- a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
+++ b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
@@ -28,6 +28,7 @@
private int precaptureTriggerId;
private long frameNumber;
private int partialResultCount;
+ private int errorStreamId;
public static final Parcelable.Creator<CaptureResultExtras> CREATOR =
new Parcelable.Creator<CaptureResultExtras>() {
@@ -48,13 +49,14 @@
public CaptureResultExtras(int requestId, int subsequenceId, int afTriggerId,
int precaptureTriggerId, long frameNumber,
- int partialResultCount) {
+ int partialResultCount, int errorStreamId) {
this.requestId = requestId;
this.subsequenceId = subsequenceId;
this.afTriggerId = afTriggerId;
this.precaptureTriggerId = precaptureTriggerId;
this.frameNumber = frameNumber;
this.partialResultCount = partialResultCount;
+ this.errorStreamId = errorStreamId;
}
@Override
@@ -70,6 +72,7 @@
dest.writeInt(precaptureTriggerId);
dest.writeLong(frameNumber);
dest.writeInt(partialResultCount);
+ dest.writeInt(errorStreamId);
}
public void readFromParcel(Parcel in) {
@@ -79,6 +82,7 @@
precaptureTriggerId = in.readInt();
frameNumber = in.readLong();
partialResultCount = in.readInt();
+ errorStreamId = in.readInt();
}
public int getRequestId() {
@@ -104,4 +108,8 @@
public int getPartialResultCount() {
return partialResultCount;
}
+
+ public int getErrorStreamId() {
+ return errorStreamId;
+ }
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index 4c4adea..661edd7 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -91,11 +91,11 @@
private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) {
if (holder == null) {
return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE,
- ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE);
+ ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE);
}
return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(),
/*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber(),
- /*partialResultCount*/1);
+ /*partialResultCount*/1, /*errorStreamId*/-1);
}
/**