Merge "Instead of returning an error, return an invalid duration (-1 ms)" into jb-mr2-dev
diff --git a/camera/tests/Android.mk b/camera/tests/Android.mk
index e455943..ec13911 100644
--- a/camera/tests/Android.mk
+++ b/camera/tests/Android.mk
@@ -35,4 +35,4 @@
LOCAL_MODULE:= camera_client_test
LOCAL_MODULE_TAGS := tests
-include $(BUILD_EXECUTABLE)
+include $(BUILD_NATIVE_TEST)
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 96baf34..5cfe5bc 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -46,6 +46,7 @@
kWhatInputSurfaceCreated = 'isfc',
kWhatSignaledInputEOS = 'seos',
kWhatBuffersAllocated = 'allc',
+ kWhatOMXDied = 'OMXd',
};
ACodec();
@@ -97,6 +98,7 @@
struct ExecutingToIdleState;
struct IdleToLoadedState;
struct FlushingState;
+ struct DeathNotifier;
enum {
kWhatSetup = 'setu',
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ff72b71..ee49033 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -166,6 +166,24 @@
////////////////////////////////////////////////////////////////////////////////
+struct ACodec::DeathNotifier : public IBinder::DeathRecipient {
+ DeathNotifier(const sp<AMessage> ¬ify)
+ : mNotify(notify) {
+ }
+
+ virtual void binderDied(const wp<IBinder> &) {
+ mNotify->post();
+ }
+
+protected:
+ virtual ~DeathNotifier() {}
+
+private:
+ sp<AMessage> mNotify;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
+};
+
struct ACodec::UninitializedState : public ACodec::BaseState {
UninitializedState(ACodec *codec);
@@ -177,6 +195,8 @@
void onSetup(const sp<AMessage> &msg);
bool onAllocateComponent(const sp<AMessage> &msg);
+ sp<DeathNotifier> mDeathNotifier;
+
DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
};
@@ -1432,14 +1452,6 @@
CHECK_EQ(err, (status_t)OK);
CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
- CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
- || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
- || format.eColorFormat == OMX_COLOR_FormatCbYCrY
- || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
- || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
- || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka
- || format.eColorFormat == OMX_SEC_COLOR_FormatNV12Tiled);
-
return mOMX->setParameter(
mNode, OMX_IndexParamVideoPortFormat,
&format, sizeof(format));
@@ -2487,6 +2499,13 @@
return true;
}
+ case ACodec::kWhatOMXDied:
+ {
+ ALOGE("OMX/mediaserver died, signalling error!");
+ mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
+ break;
+ }
+
default:
return false;
}
@@ -3035,6 +3054,18 @@
void ACodec::UninitializedState::stateEntered() {
ALOGV("Now uninitialized");
+
+ if (mDeathNotifier != NULL) {
+ mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier);
+ mDeathNotifier.clear();
+ }
+
+ mCodec->mNativeWindow.clear();
+ mCodec->mNode = NULL;
+ mCodec->mOMX.clear();
+ mCodec->mQuirks = 0;
+ mCodec->mFlags = 0;
+ mCodec->mComponentName.clear();
}
bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
@@ -3106,6 +3137,15 @@
sp<IOMX> omx = client.interface();
+ sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id());
+
+ mDeathNotifier = new DeathNotifier(notify);
+ if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) {
+ // This was a local binder, if it dies so do we, we won't care
+ // about any notifications in the afterlife.
+ mDeathNotifier.clear();
+ }
+
Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
AString mime;
@@ -3170,7 +3210,7 @@
return false;
}
- sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
+ notify = new AMessage(kWhatOMXMessage, mCodec->id());
observer->setNotificationMessage(notify);
mCodec->mComponentName = componentName;
@@ -3224,13 +3264,6 @@
if (!keepComponentAllocated) {
CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
- mCodec->mNativeWindow.clear();
- mCodec->mNode = NULL;
- mCodec->mOMX.clear();
- mCodec->mQuirks = 0;
- mCodec->mFlags = 0;
- mCodec->mComponentName.clear();
-
mCodec->changeState(mCodec->mUninitializedState);
}
@@ -3626,7 +3659,6 @@
(status_t)OK);
mCodec->changeState(mCodec->mFlushingState);
-
handled = true;
break;
}
@@ -4141,6 +4173,10 @@
mCodec->mInputEOSResult = OK;
+ if (mCodec->mSkipCutBuffer != NULL) {
+ mCodec->mSkipCutBuffer->clear();
+ }
+
mCodec->changeState(mCodec->mExecutingState);
}
}
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index ff72e0e..1822f07 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -32,7 +32,7 @@
MuxOMX(const sp<IOMX> &remoteOMX);
virtual ~MuxOMX();
- virtual IBinder *onAsBinder() { return NULL; }
+ virtual IBinder *onAsBinder() { return mRemoteOMX->asBinder().get(); }
virtual bool livesLocally(node_id node, pid_t pid);
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 22aefcc..6c0779d 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1213,13 +1213,6 @@
CHECK_EQ(err, (status_t)OK);
CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
- CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
- || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
- || format.eColorFormat == OMX_COLOR_FormatCbYCrY
- || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
- || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
- || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka);
-
int32_t colorFormat;
if (meta->findInt32(kKeyColorFormat, &colorFormat)
&& colorFormat != OMX_COLOR_FormatUnused
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index a8ab2ac..8ba2afb 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -118,7 +118,7 @@
status = OK;
}
}
- mIsFirst = true;
+ mDecoderHasData = false;
// for streams that contain metadata, use the mobile profile DRC settings unless overridden
// by platform properties:
@@ -327,6 +327,7 @@
notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
return;
}
+
inQueue.erase(inQueue.begin());
info->mOwnedByUs = false;
notifyEmptyBufferDone(header);
@@ -358,7 +359,7 @@
inInfo->mOwnedByUs = false;
notifyEmptyBufferDone(inHeader);
- if (!mIsFirst) {
+ if (mDecoderHasData) {
// flush out the decoder's delayed data by calling DecodeFrame
// one more time, with the AACDEC_FLUSH flag set
INT_PCM *outBuffer =
@@ -370,6 +371,7 @@
outBuffer,
outHeader->nAllocLen,
AACDEC_FLUSH);
+ mDecoderHasData = false;
if (decoderErr != AAC_DEC_OK) {
mSignalledError = true;
@@ -385,9 +387,7 @@
* sizeof(int16_t)
* mStreamInfo->numChannels;
} else {
- // Since we never discarded frames from the start, we won't have
- // to add any padding at the end either.
-
+ // we never submitted any data to the decoder, so there's nothing to flush out
outHeader->nFilledLen = 0;
}
@@ -473,6 +473,7 @@
inBuffer,
inBufferLength,
bytesValid);
+ mDecoderHasData = true;
decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
outBuffer,
@@ -484,45 +485,6 @@
}
}
- /*
- * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
- * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
- * rate system and the sampling rate in the final output is actually
- * doubled compared with the core AAC decoder sampling rate.
- *
- * Explicit signalling is done by explicitly defining SBR audio object
- * type in the bitstream. Implicit signalling is done by embedding
- * SBR content in AAC extension payload specific to SBR, and hence
- * requires an AAC decoder to perform pre-checks on actual audio frames.
- *
- * Thus, we could not say for sure whether a stream is
- * AAC+/eAAC+ until the first data frame is decoded.
- */
- if (mInputBufferCount <= 2) {
- if (mStreamInfo->sampleRate != prevSampleRate ||
- mStreamInfo->numChannels != prevNumChannels) {
- maybeConfigureDownmix();
- ALOGI("Reconfiguring decoder: %d Hz, %d channels",
- mStreamInfo->sampleRate,
- mStreamInfo->numChannels);
-
- // We're going to want to revisit this input buffer, but
- // may have already advanced the offset. Undo that if
- // necessary.
- inHeader->nOffset -= adtsHeaderSize;
- inHeader->nFilledLen += adtsHeaderSize;
-
- notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
- mOutputPortSettingsChange = AWAITING_DISABLED;
- return;
- }
- } else if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) {
- ALOGW("Invalid AAC stream");
- mSignalledError = true;
- notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
- return;
- }
-
size_t numOutBytes =
mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels;
@@ -544,17 +506,51 @@
// fall through
}
+ if (inHeader->nFilledLen == 0) {
+ inInfo->mOwnedByUs = false;
+ inQueue.erase(inQueue.begin());
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+ }
+
+ /*
+ * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
+ * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
+ * rate system and the sampling rate in the final output is actually
+ * doubled compared with the core AAC decoder sampling rate.
+ *
+ * Explicit signalling is done by explicitly defining SBR audio object
+ * type in the bitstream. Implicit signalling is done by embedding
+ * SBR content in AAC extension payload specific to SBR, and hence
+ * requires an AAC decoder to perform pre-checks on actual audio frames.
+ *
+ * Thus, we could not say for sure whether a stream is
+ * AAC+/eAAC+ until the first data frame is decoded.
+ */
+ if (mInputBufferCount <= 2) {
+ if (mStreamInfo->sampleRate != prevSampleRate ||
+ mStreamInfo->numChannels != prevNumChannels) {
+ maybeConfigureDownmix();
+ ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels",
+ prevSampleRate, mStreamInfo->sampleRate,
+ prevNumChannels, mStreamInfo->numChannels);
+
+ notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+ mOutputPortSettingsChange = AWAITING_DISABLED;
+ return;
+ }
+ } else if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) {
+ ALOGW("Invalid AAC stream");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
+ return;
+ }
+
if (decoderErr == AAC_DEC_OK || mNumSamplesOutput > 0) {
// We'll only output data if we successfully decoded it or
// we've previously decoded valid data, in the latter case
// (decode failed) we'll output a silent frame.
- if (mIsFirst) {
- mIsFirst = false;
- // the first decoded frame should be discarded to account
- // for decoder delay
- numOutBytes = 0;
- }
-
outHeader->nFilledLen = numOutBytes;
outHeader->nFlags = 0;
@@ -571,14 +567,6 @@
outHeader = NULL;
}
- if (inHeader->nFilledLen == 0) {
- inInfo->mOwnedByUs = false;
- inQueue.erase(inQueue.begin());
- inInfo = NULL;
- notifyEmptyBufferDone(inHeader);
- inHeader = NULL;
- }
-
if (decoderErr == AAC_DEC_OK) {
++mInputBufferCount;
}
@@ -589,14 +577,21 @@
if (portIndex == 0) {
// Make sure that the next buffer output does not still
// depend on fragments from the last one decoded.
- aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
- mIsFirst = true;
+ // drain all existing data
+ drainDecoder();
}
}
-void SoftAAC2::onReset() {
+void SoftAAC2::drainDecoder() {
+ short buf [2048];
+ aacDecoder_DecodeFrame(mAACDecoder, buf, 4096, AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
+ aacDecoder_DecodeFrame(mAACDecoder, buf, 4096, AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
- mIsFirst = true;
+ mDecoderHasData = false;
+}
+
+void SoftAAC2::onReset() {
+ drainDecoder();
}
void SoftAAC2::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.h b/media/libstagefright/codecs/aacdec/SoftAAC2.h
index 6957ade..2d960ab 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.h
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.h
@@ -52,7 +52,7 @@
HANDLE_AACDECODER mAACDecoder;
CStreamInfo *mStreamInfo;
bool mIsADTS;
- bool mIsFirst;
+ bool mDecoderHasData;
size_t mInputBufferCount;
bool mSignalledError;
int64_t mAnchorTimeUs;
@@ -68,6 +68,7 @@
status_t initDecoder();
bool isConfigured() const;
void maybeConfigureDownmix() const;
+ void drainDecoder();
DISALLOW_EVIL_CONSTRUCTORS(SoftAAC2);
};
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 46ff22f..971875f 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -292,15 +292,14 @@
status_t OMXNodeInstance::enableGraphicBuffers(
OMX_U32 portIndex, OMX_BOOL enable) {
Mutex::Autolock autoLock(mLock);
+ OMX_STRING name = const_cast<OMX_STRING>(
+ "OMX.google.android.index.enableAndroidNativeBuffers");
OMX_INDEXTYPE index;
- OMX_ERRORTYPE err = OMX_GetExtensionIndex(
- mHandle,
- const_cast<OMX_STRING>("OMX.google.android.index.enableAndroidNativeBuffers"),
- &index);
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex failed");
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
return StatusFromOMXError(err);
}
@@ -331,14 +330,12 @@
Mutex::Autolock autoLock(mLock);
OMX_INDEXTYPE index;
- OMX_ERRORTYPE err = OMX_GetExtensionIndex(
- mHandle,
- const_cast<OMX_STRING>(
- "OMX.google.android.index.getAndroidNativeBufferUsage"),
- &index);
+ OMX_STRING name = const_cast<OMX_STRING>(
+ "OMX.google.android.index.getAndroidNativeBufferUsage");
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex failed");
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
return StatusFromOMXError(err);
}
@@ -381,7 +378,9 @@
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex %s failed", name);
+ if (enable) {
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
+ }
return StatusFromOMXError(err);
}
@@ -507,13 +506,12 @@
return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
}
- OMX_ERRORTYPE err = OMX_GetExtensionIndex(
- mHandle,
- const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer"),
- &index);
+ OMX_STRING name = const_cast<OMX_STRING>(
+ "OMX.google.android.index.useAndroidNativeBuffer");
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex failed");
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
return StatusFromOMXError(err);
}
diff --git a/services/camera/libcameraservice/Camera3Device.cpp b/services/camera/libcameraservice/Camera3Device.cpp
index e53dbb5..08aef83 100644
--- a/services/camera/libcameraservice/Camera3Device.cpp
+++ b/services/camera/libcameraservice/Camera3Device.cpp
@@ -25,6 +25,18 @@
#define ALOGVV(...) ((void)0)
#endif
+// Convenience macro for transient errors
+#define CLOGE(fmt, ...) ALOGE("Camera %d: %s: " fmt, mId, __FUNCTION__, \
+ ##__VA_ARGS__)
+
+// Convenience macros for transitioning to the error state
+#define SET_ERR(fmt, ...) setErrorState( \
+ "%s: " fmt, __FUNCTION__, \
+ ##__VA_ARGS__)
+#define SET_ERR_L(fmt, ...) setErrorStateLocked( \
+ "%s: " fmt, __FUNCTION__, \
+ ##__VA_ARGS__)
+
#include <utils/Log.h>
#include <utils/Trace.h>
#include <utils/Timers.h>
@@ -69,7 +81,7 @@
ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);
if (mStatus != STATUS_UNINITIALIZED) {
- ALOGE("%s: Already initialized!", __FUNCTION__);
+ CLOGE("Already initialized!");
return INVALID_OPERATION;
}
@@ -84,21 +96,18 @@
reinterpret_cast<hw_device_t**>(&device));
if (res != OK) {
- ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
- mId, strerror(-res), res);
- mStatus = STATUS_ERROR;
+ SET_ERR_L("Could not open camera: %s (%d)", strerror(-res), res);
return res;
}
/** Cross-check device version */
if (device->common.version != CAMERA_DEVICE_API_VERSION_3_0) {
- ALOGE("%s: Could not open camera %d: "
+ SET_ERR_L("Could not open camera: "
"Camera device is not version %x, reports %x instead",
- __FUNCTION__, mId, CAMERA_DEVICE_API_VERSION_3_0,
+ CAMERA_DEVICE_API_VERSION_3_0,
device->common.version);
device->common.close(&device->common);
- mStatus = STATUS_ERROR;
return BAD_VALUE;
}
@@ -107,11 +116,10 @@
if (res != OK) return res;
if (info.device_version != device->common.version) {
- ALOGE("%s: HAL reporting mismatched camera_info version (%x)"
- " and device version (%x).", __FUNCTION__,
+ SET_ERR_L("HAL reporting mismatched camera_info version (%x)"
+ " and device version (%x).",
device->common.version, info.device_version);
device->common.close(&device->common);
- mStatus = STATUS_ERROR;
return BAD_VALUE;
}
@@ -119,10 +127,9 @@
res = device->ops->initialize(device, this);
if (res != OK) {
- ALOGE("%s: Camera %d: Unable to initialize HAL device: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
+ SET_ERR_L("Unable to initialize HAL device: %s (%d)",
+ strerror(-res), res);
device->common.close(&device->common);
- mStatus = STATUS_ERROR;
return BAD_VALUE;
}
@@ -135,10 +142,9 @@
if (mVendorTagOps.get_camera_vendor_section_name != NULL) {
res = set_camera_metadata_vendor_tag_ops(&mVendorTagOps);
if (res != OK) {
- ALOGE("%s: Camera %d: Unable to set tag ops: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
+ SET_ERR_L("Unable to set tag ops: %s (%d)",
+ strerror(-res), res);
device->common.close(&device->common);
- mStatus = STATUS_ERROR;
return res;
}
}
@@ -148,11 +154,10 @@
mRequestThread = new RequestThread(this, device);
res = mRequestThread->run(String8::format("C3Dev-%d-ReqQueue", mId).string());
if (res != OK) {
- ALOGE("%s: Camera %d: Unable to start request queue thread: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
+ SET_ERR_L("Unable to start request queue thread: %s (%d)",
+ strerror(-res), res);
device->common.close(&device->common);
mRequestThread.clear();
- mStatus = STATUS_ERROR;
return res;
}
@@ -179,12 +184,12 @@
(mStatus == STATUS_ERROR && mRequestThread != NULL)) {
res = mRequestThread->clearRepeatingRequests();
if (res != OK) {
- ALOGE("%s: Can't stop streaming", __FUNCTION__);
+ SET_ERR_L("Can't stop streaming");
return res;
}
res = waitUntilDrainedLocked();
if (res != OK) {
- ALOGE("%s: Timeout waiting for HAL to drain", __FUNCTION__);
+ SET_ERR_L("Timeout waiting for HAL to drain");
return res;
}
}
@@ -225,6 +230,9 @@
mStatus == STATUS_ACTIVE ? "ACTIVE" :
"Unknown";
lines.appendFormat(" Device status: %s\n", status);
+ if (mStatus == STATUS_ERROR) {
+ lines.appendFormat(" Error cause: %s\n", mErrorCause.string());
+ }
lines.appendFormat(" Stream configuration:\n");
if (mInputStream != NULL) {
@@ -251,7 +259,7 @@
ALOGVV("%s: E", __FUNCTION__);
if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
mStatus == STATUS_ERROR)) {
- ALOGE("%s: Access to static info %s!", __FUNCTION__,
+ ALOGW("%s: Access to static info %s!", __FUNCTION__,
mStatus == STATUS_ERROR ?
"when in error state" : "before init");
}
@@ -266,23 +274,23 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
sp<CaptureRequest> newRequest = setUpRequestLocked(request);
if (newRequest == NULL) {
- ALOGE("%s: Can't create capture request", __FUNCTION__);
+ CLOGE("Can't create capture request");
return BAD_VALUE;
}
@@ -296,23 +304,23 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
sp<CaptureRequest> newRepeatingRequest = setUpRequestLocked(request);
if (newRepeatingRequest == NULL) {
- ALOGE("%s: Can't create repeating request", __FUNCTION__);
+ CLOGE("Can't create repeating request");
return BAD_VALUE;
}
@@ -330,8 +338,7 @@
if (mStatus == STATUS_IDLE) {
res = configureStreamsLocked();
if (res != OK) {
- ALOGE("%s: Can't set up streams: %s (%d)",
- __FUNCTION__, strerror(-res), res);
+ SET_ERR_L("Can't set up streams: %s (%d)", strerror(-res), res);
return NULL;
}
}
@@ -346,17 +353,17 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
@@ -379,10 +386,10 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
// OK
@@ -394,13 +401,12 @@
if (res != OK) {
ALOGE("%s: Can't pause captures to reconfigure streams!",
__FUNCTION__);
- mStatus = STATUS_ERROR;
return res;
}
wasActive = true;
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
assert(mStatus == STATUS_IDLE);
@@ -416,8 +422,7 @@
res = mOutputStreams.add(mNextStreamId, newStream);
if (res < 0) {
- ALOGE("%s: Can't add new stream to set: %s (%d)",
- __FUNCTION__, strerror(-res), res);
+ SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
return res;
}
@@ -428,8 +433,8 @@
ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
res = configureStreamsLocked();
if (res != OK) {
- ALOGE("%s: Can't reconfigure device for new stream %d: %s (%d)",
- __FUNCTION__, mNextStreamId, strerror(-res), res);
+ CLOGE("Can't reconfigure device for new stream %d: %s (%d)",
+ mNextStreamId, strerror(-res), res);
return res;
}
mRequestThread->setPaused(false);
@@ -442,7 +447,7 @@
ATRACE_CALL();
(void)outputId; (void)id;
- ALOGE("%s: Unimplemented", __FUNCTION__);
+ CLOGE("Unimplemented");
return INVALID_OPERATION;
}
@@ -454,23 +459,23 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized!", __FUNCTION__);
+ CLOGE("Device not initialized!");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
ssize_t idx = mOutputStreams.indexOfKey(id);
if (idx == NAME_NOT_FOUND) {
- ALOGE("%s: Stream %d is unknown", __FUNCTION__, id);
+ CLOGE("Stream %d is unknown", id);
return idx;
}
@@ -488,24 +493,24 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
ssize_t idx = mOutputStreams.indexOfKey(id);
if (idx == NAME_NOT_FOUND) {
- ALOGE("%s: Stream %d does not exist",
- __FUNCTION__, id);
+ CLOGE("Stream %d does not exist",
+ id);
return BAD_VALUE;
}
@@ -520,7 +525,7 @@
// CameraDevice semantics require device to already be idle before
// deleteStream is called, unlike for createStream.
if (mStatus != STATUS_IDLE) {
- ALOGE("%s: Device not idle", __FUNCTION__);
+ CLOGE("Device not idle");
return INVALID_OPERATION;
}
@@ -531,8 +536,7 @@
} else {
ssize_t idx = mOutputStreams.indexOfKey(id);
if (idx == NAME_NOT_FOUND) {
- ALOGE("%s: Stream %d does not exist",
- __FUNCTION__, id);
+ CLOGE("Stream %d does not exist", id);
return BAD_VALUE;
}
deletedStream = mOutputStreams.editValueAt(idx);
@@ -542,7 +546,7 @@
// Free up the stream endpoint so that it can be used by some other stream
res = deletedStream->disconnect();
if (res != OK) {
- ALOGE("%s: Can't disconnect deleted stream", __FUNCTION__);
+ SET_ERR_L("Can't disconnect deleted stream %d", id);
// fall through since we want to still list the stream as deleted.
}
mDeletedStreams.add(deletedStream);
@@ -554,7 +558,7 @@
ATRACE_CALL();
(void)id;
- ALOGE("%s: Unimplemented", __FUNCTION__);
+ CLOGE("Unimplemented");
return INVALID_OPERATION;
}
@@ -567,24 +571,28 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device is not initialized!", __FUNCTION__);
+ CLOGE("Device is not initialized!");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
const camera_metadata_t *rawRequest;
rawRequest = mHal3Device->ops->construct_default_request_settings(
mHal3Device, templateId);
- if (rawRequest == NULL) return DEAD_OBJECT;
+ if (rawRequest == NULL) {
+ SET_ERR_L("HAL is unable to construct default settings for template %d",
+ templateId);
+ return DEAD_OBJECT;
+ }
*request = rawRequest;
return OK;
@@ -611,35 +619,31 @@
// Need to shut down
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d",mStatus);
return INVALID_OPERATION;
}
if (mRequestThread != NULL) {
res = mRequestThread->waitUntilPaused(kShutdownTimeout);
if (res != OK) {
- ALOGE("%s: Can't stop request thread in %f seconds!",
- __FUNCTION__, kShutdownTimeout/1e9);
- mStatus = STATUS_ERROR;
+ SET_ERR_L("Can't stop request thread in %f seconds!",
+ kShutdownTimeout/1e9);
return res;
}
}
if (mInputStream != NULL) {
res = mInputStream->waitUntilIdle(kShutdownTimeout);
if (res != OK) {
- ALOGE("%s: Can't idle input stream %d in %f seconds!",
- __FUNCTION__, mInputStream->getId(), kShutdownTimeout/1e9);
- mStatus = STATUS_ERROR;
+ SET_ERR_L("Can't idle input stream %d in %f seconds!",
+ mInputStream->getId(), kShutdownTimeout/1e9);
return res;
}
}
for (size_t i = 0; i < mOutputStreams.size(); i++) {
res = mOutputStreams.editValueAt(i)->waitUntilIdle(kShutdownTimeout);
if (res != OK) {
- ALOGE("%s: Can't idle output stream %d in %f seconds!",
- __FUNCTION__, mOutputStreams.keyAt(i),
- kShutdownTimeout/1e9);
- mStatus = STATUS_ERROR;
+ SET_ERR_L("Can't idle output stream %d in %f seconds!",
+ mOutputStreams.keyAt(i), kShutdownTimeout/1e9);
return res;
}
}
@@ -673,8 +677,8 @@
if (res == TIMED_OUT) {
return res;
} else if (res != OK) {
- ALOGE("%s: Camera %d: Error waiting for frame: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
+ ALOGW("%s: Camera %d: No frame in %lld ns: %s (%d)",
+ __FUNCTION__, mId, timeout, strerror(-res), res);
return res;
}
}
@@ -761,7 +765,7 @@
ATRACE_CALL();
(void)reprocessStreamId; (void)buffer; (void)listener;
- ALOGE("%s: Unimplemented", __FUNCTION__);
+ CLOGE("Unimplemented");
return INVALID_OPERATION;
}
@@ -782,8 +786,8 @@
if (inputStreams.count > 0) {
if (mInputStream == NULL ||
mInputStream->getId() != inputStreams.data.u8[0]) {
- ALOGE("%s: Request references unknown input stream %d",
- __FUNCTION__, inputStreams.data.u8[0]);
+ CLOGE("Request references unknown input stream %d",
+ inputStreams.data.u8[0]);
return NULL;
}
// Lazy completion of stream configuration (allocation/registration)
@@ -791,10 +795,9 @@
if (mInputStream->isConfiguring()) {
res = mInputStream->finishConfiguration(mHal3Device);
if (res != OK) {
- ALOGE("%s: Unable to finish configuring input stream %d:"
+ SET_ERR_L("Unable to finish configuring input stream %d:"
" %s (%d)",
- __FUNCTION__, mInputStream->getId(),
- strerror(-res), res);
+ mInputStream->getId(), strerror(-res), res);
return NULL;
}
}
@@ -806,15 +809,15 @@
camera_metadata_entry_t streams =
newRequest->mSettings.find(ANDROID_REQUEST_OUTPUT_STREAMS);
if (streams.count == 0) {
- ALOGE("%s: Zero output streams specified!", __FUNCTION__);
+ CLOGE("Zero output streams specified!");
return NULL;
}
for (size_t i = 0; i < streams.count; i++) {
int idx = mOutputStreams.indexOfKey(streams.data.u8[i]);
if (idx == NAME_NOT_FOUND) {
- ALOGE("%s: Request references unknown stream %d",
- __FUNCTION__, streams.data.u8[i]);
+ CLOGE("Request references unknown stream %d",
+ streams.data.u8[i]);
return NULL;
}
sp<Camera3OutputStream> stream = mOutputStreams.editValueAt(idx);
@@ -824,8 +827,8 @@
if (stream->isConfiguring()) {
res = stream->finishConfiguration(mHal3Device);
if (res != OK) {
- ALOGE("%s: Unable to finish configuring stream %d: %s (%d)",
- __FUNCTION__, stream->getId(), strerror(-res), res);
+ SET_ERR_L("Unable to finish configuring stream %d: %s (%d)",
+ stream->getId(), strerror(-res), res);
return NULL;
}
}
@@ -842,7 +845,7 @@
status_t res;
if (mStatus != STATUS_IDLE) {
- ALOGE("%s: Not idle", __FUNCTION__);
+ CLOGE("Not idle");
return INVALID_OPERATION;
}
@@ -859,9 +862,7 @@
camera3_stream_t *inputStream;
inputStream = mInputStream->startConfiguration();
if (inputStream == NULL) {
- ALOGE("%s: Can't start input stream configuration",
- __FUNCTION__);
- // TODO: Make sure the error flow here is correct
+ SET_ERR_L("Can't start input stream configuration");
return INVALID_OPERATION;
}
streams.add(inputStream);
@@ -871,9 +872,7 @@
camera3_stream_t *outputStream;
outputStream = mOutputStreams.editValueAt(i)->startConfiguration();
if (outputStream == NULL) {
- ALOGE("%s: Can't start output stream configuration",
- __FUNCTION__);
- // TODO: Make sure the error flow here is correct
+ SET_ERR_L("Can't start output stream configuration");
return INVALID_OPERATION;
}
streams.add(outputStream);
@@ -887,8 +886,8 @@
res = mHal3Device->ops->configure_streams(mHal3Device, &config);
if (res != OK) {
- ALOGE("%s: Unable to configure streams with HAL: %s (%d)",
- __FUNCTION__, strerror(-res), res);
+ SET_ERR_L("Unable to configure streams with HAL: %s (%d)",
+ strerror(-res), res);
return res;
}
@@ -903,6 +902,38 @@
return OK;
}
+void Camera3Device::setErrorState(const char *fmt, ...) {
+ Mutex::Autolock l(mLock);
+ va_list args;
+ va_start(args, fmt);
+
+ setErrorStateLockedV(fmt, args);
+
+ va_end(args);
+}
+
+void Camera3Device::setErrorStateV(const char *fmt, va_list args) {
+ Mutex::Autolock l(mLock);
+ setErrorStateLockedV(fmt, args);
+}
+
+void Camera3Device::setErrorStateLocked(const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+
+ setErrorStateLockedV(fmt, args);
+
+ va_end(args);
+}
+
+void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {
+ // Only accept the first failure cause
+ if (mStatus == STATUS_ERROR) return;
+
+ mErrorCause = String8::formatV(fmt, args);
+ ALOGE("Camera %d: %s", mId, mErrorCause.string());
+ mStatus = STATUS_ERROR;
+}
/**
* Camera HAL device callback methods
@@ -914,8 +945,7 @@
status_t res;
if (result->result == NULL) {
- // TODO: Report error upstream
- ALOGW("%s: No metadata for frame %d", __FUNCTION__,
+ SET_ERR("No metadata provided by HAL for frame %d",
result->frame_number);
return;
}
@@ -938,13 +968,12 @@
captureResult = result->result;
if (captureResult.update(ANDROID_REQUEST_FRAME_COUNT,
- (int32_t*)&result->frame_number, 1) != OK) {
- ALOGE("%s: Camera %d: Failed to set frame# in metadata (%d)",
- __FUNCTION__, mId, result->frame_number);
- // TODO: Report error upstream
+ (int32_t*)&result->frame_number, 1) != OK) {
+ SET_ERR("Failed to set frame# in metadata (%d)",
+ result->frame_number);
} else {
ALOGVV("%s: Camera %d: Set frame# in metadata (%d)",
- __FUNCTION__, mId, result->frame_number);
+ __FUNCTION__, mId, result->frame_number);
}
// Get timestamp from result metadata
@@ -952,9 +981,8 @@
camera_metadata_entry entry =
captureResult.find(ANDROID_SENSOR_TIMESTAMP);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No timestamp provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
- // TODO: Report error upstream
+ SET_ERR("No timestamp provided by HAL for frame %d!",
+ result->frame_number);
} else {
timestamp = entry.data.i64[0];
}
@@ -963,8 +991,8 @@
entry = captureResult.find(ANDROID_CONTROL_AE_STATE);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AE state provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AE state provided by HAL for frame %d!",
+ result->frame_number);
} else {
new3aState.aeState =
static_cast<camera_metadata_enum_android_control_ae_state>(
@@ -973,8 +1001,8 @@
entry = captureResult.find(ANDROID_CONTROL_AF_STATE);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AF state provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AF state provided by HAL for frame %d!",
+ result->frame_number);
} else {
new3aState.afState =
static_cast<camera_metadata_enum_android_control_af_state>(
@@ -983,8 +1011,8 @@
entry = captureResult.find(ANDROID_CONTROL_AWB_STATE);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AWB state provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AWB state provided by HAL for frame %d!",
+ result->frame_number);
} else {
new3aState.awbState =
static_cast<camera_metadata_enum_android_control_awb_state>(
@@ -993,16 +1021,16 @@
entry = captureResult.find(ANDROID_CONTROL_AF_TRIGGER_ID);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AF trigger ID provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AF trigger ID provided by HAL for frame %d!",
+ result->frame_number);
} else {
afTriggerId = entry.data.i32[0];
}
entry = captureResult.find(ANDROID_CONTROL_AE_PRECAPTURE_ID);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AE precapture trigger ID provided by HAL"
- " for frame %d!", __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AE precapture trigger ID provided by HAL"
+ " for frame %d!", result->frame_number);
} else {
aeTriggerId = entry.data.i32[0];
}
@@ -1021,10 +1049,8 @@
// Note: stream may be deallocated at this point, if this buffer was the
// last reference to it.
if (res != OK) {
- ALOGE("%s: Camera %d: Can't return buffer %d for frame %d to its"
- " stream:%s (%d)", __FUNCTION__, mId, i,
- result->frame_number, strerror(-res), res);
- // TODO: Report error upstream
+ SET_ERR("Can't return buffer %d for frame %d to its stream: "
+ " %s (%d)", i, result->frame_number, strerror(-res), res);
}
}
@@ -1056,8 +1082,7 @@
}
if (msg == NULL) {
- ALOGE("%s: Camera %d: HAL sent NULL notify message!",
- __FUNCTION__, mId);
+ SET_ERR_L("HAL sent NULL notify message!");
return;
}
@@ -1080,8 +1105,8 @@
break;
}
default:
- ALOGE("%s: Camera %d: Unknown notify message from HAL: %d",
- __FUNCTION__, mId, msg->type);
+ SET_ERR_L("Unknown notify message from HAL: %d",
+ msg->type);
}
}
@@ -1240,9 +1265,9 @@
int32_t triggerCount;
res = insertTriggers(nextRequest);
if (res < 0) {
- ALOGE("RequestThread: Unable to insert triggers "
- "(capture request %d, HAL device: %s (%d)",
- (mFrameNumber+1), strerror(-res), res);
+ SET_ERR("RequestThread: Unable to insert triggers "
+ "(capture request %d, HAL device: %s (%d)",
+ (mFrameNumber+1), strerror(-res), res);
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return false;
}
@@ -1289,7 +1314,7 @@
request.input_buffer = &inputBuffer;
res = nextRequest->mInputStream->getBuffer(&inputBuffer);
if (res != OK) {
- ALOGE("RequestThread: Can't get input buffer, skipping request:"
+ SET_ERR("RequestThread: Can't get input buffer, skipping request:"
" %s (%d)", strerror(-res), res);
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return true;
@@ -1305,7 +1330,7 @@
res = nextRequest->mOutputStreams.editItemAt(i)->
getBuffer(&outputBuffers.editItemAt(i));
if (res != OK) {
- ALOGE("RequestThread: Can't get output buffer, skipping request:"
+ SET_ERR("RequestThread: Can't get output buffer, skipping request:"
"%s (%d)", strerror(-res), res);
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return true;
@@ -1320,7 +1345,7 @@
res = mHal3Device->ops->process_capture_request(mHal3Device, &request);
if (res != OK) {
- ALOGE("RequestThread: Unable to submit capture request %d to HAL"
+ SET_ERR("RequestThread: Unable to submit capture request %d to HAL"
" device: %s (%d)", request.frame_number, strerror(-res), res);
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return false;
@@ -1333,7 +1358,7 @@
// Remove any previously queued triggers (after unlock)
res = removeTriggers(mPrevRequest);
if (res != OK) {
- ALOGE("RequestThread: Unable to remove triggers "
+ SET_ERR("RequestThread: Unable to remove triggers "
"(capture request %d, HAL device: %s (%d)",
request.frame_number, strerror(-res), res);
return false;
@@ -1378,7 +1403,6 @@
nextRequest->mOutputStreams.editItemAt(i)->returnBuffer(
outputBuffers[i], 0);
}
- // TODO: Report error upstream
}
sp<Camera3Device::CaptureRequest>
@@ -1462,6 +1486,18 @@
return false;
}
+void Camera3Device::RequestThread::setErrorState(const char *fmt, ...) {
+ sp<Camera3Device> parent = mParent.promote();
+ if (parent != NULL) {
+ va_list args;
+ va_start(args, fmt);
+
+ parent->setErrorStateV(fmt, args);
+
+ va_end(args);
+ }
+}
+
status_t Camera3Device::RequestThread::insertTriggers(
const sp<CaptureRequest> &request) {
diff --git a/services/camera/libcameraservice/Camera3Device.h b/services/camera/libcameraservice/Camera3Device.h
index 7f294e6..2e4a303 100644
--- a/services/camera/libcameraservice/Camera3Device.h
+++ b/services/camera/libcameraservice/Camera3Device.h
@@ -128,6 +128,9 @@
STATUS_ACTIVE
} mStatus;
+ // Tracking cause of fatal errors when in STATUS_ERROR
+ String8 mErrorCause;
+
// Mapping of stream IDs to stream instances
typedef KeyedVector<int, sp<camera3::Camera3OutputStream> > StreamSet;
@@ -172,6 +175,16 @@
*/
status_t configureStreamsLocked();
+ /**
+ * Set device into an error state due to some fatal failure, and set an
+ * error message to indicate why. Only the first call's message will be
+ * used. The message is also sent to the log.
+ */
+ void setErrorState(const char *fmt, ...);
+ void setErrorStateV(const char *fmt, va_list args);
+ void setErrorStateLocked(const char *fmt, ...);
+ void setErrorStateLockedV(const char *fmt, va_list args);
+
struct RequestTrigger {
// Metadata tag number, e.g. android.control.aePrecaptureTrigger
uint32_t metadataTag;
@@ -272,6 +285,9 @@
// Pause handling
bool waitIfPaused();
+ // Relay error to parent device object setErrorState
+ void setErrorState(const char *fmt, ...);
+
wp<Camera3Device> mParent;
camera3_device_t *mHal3Device;