Camera: Stop repeating request if its output is abandoned
Stop repeating request if any of its output stream is abandoned.
Add a callback to notify the repeating request has been stopped
with frame number of the last frame.
Update NDK with the new callback and behavior.
Bug: 21270879
Change-Id: I3553775c7807a77104aa1650609480ca3321310c
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl
index ab57db5..755ec8e 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl
@@ -37,4 +37,11 @@
oneway void onResultReceived(in CameraMetadataNative result,
in CaptureResultExtras resultExtras);
oneway void onPrepared(int streamId);
+
+ /**
+ * Repeating request encountered an error and was stopped.
+ *
+ * @param lastFrameNumber Frame number of the last frame of the streaming request.
+ */
+ oneway void onRepeatingRequestError(in long lastFrameNumber);
}
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
index 250f15e..1e8744b 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -36,7 +36,10 @@
* Cancel the repeating request specified by requestId
* Returns the frame number of the last frame that will be produced from this
* repeating request, or NO_IN_FLIGHT_REPEATING_FRAMES if no frames were produced
- * by this repeating request
+ * by this repeating request.
+ *
+ * Repeating request may be stopped by camera device due to an error. Canceling a stopped
+ * repeating request will trigger ERROR_ILLEGAL_ARGUMENT.
*/
long cancelRequest(int requestId);
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 0b758b6..bff5547 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -380,7 +380,11 @@
int64_t lastFrameNumber;
binder::Status remoteRet = mRemote->cancelRequest(repeatingSequenceId, &lastFrameNumber);
- if (!remoteRet.isOk()) {
+ if (remoteRet.serviceSpecificErrorCode() ==
+ hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT) {
+ ALOGV("Repeating request is already stopped.");
+ return ACAMERA_OK;
+ } else if (!remoteRet.isOk()) {
ALOGE("Stop repeating request fails in remote: %s", remoteRet.toString8().string());
return ACAMERA_ERROR_UNKNOWN;
}
@@ -1342,4 +1346,24 @@
return binder::Status::ok();
}
+binder::Status
+CameraDevice::ServiceCallback::onRepeatingRequestError(int64_t lastFrameNumber) {
+ binder::Status ret = binder::Status::ok();
+
+ sp<CameraDevice> dev = mDevice.promote();
+ if (dev == nullptr) {
+ return ret; // device has been closed
+ }
+
+ Mutex::Autolock _l(dev->mDeviceLock);
+
+ int repeatingSequenceId = dev->mRepeatingSequenceId;
+ dev->mRepeatingSequenceId = REQUEST_ID_NONE;
+
+ dev->checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
+
+ return ret;
+}
+
+
} // namespace android
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 3ccf95a..71e364d 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -74,6 +74,7 @@
binder::Status onResultReceived(const CameraMetadata& metadata,
const CaptureResultExtras& resultExtras) override;
binder::Status onPrepared(int streamId) override;
+ binder::Status onRepeatingRequestError(int64_t lastFrameNumber) override;
private:
const wp<CameraDevice> mDevice;
};
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index 0b687b4..828a758 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -149,7 +149,8 @@
PREPARED,
RUNNING,
SENT_RESULT,
- UNINITIALIZED
+ UNINITIALIZED,
+ REPEATING_REQUEST_ERROR,
};
protected:
@@ -215,6 +216,15 @@
return binder::Status::ok();
}
+ virtual binder::Status onRepeatingRequestError(int64_t lastFrameNumber) {
+ (void) lastFrameNumber;
+ Mutex::Autolock l(mLock);
+ mLastStatus = REPEATING_REQUEST_ERROR;
+ mStatusesHit.push_back(mLastStatus);
+ mStatusCondition.broadcast();
+ return binder::Status::ok();
+ }
+
// Test helper functions:
bool hadError() const {