Android: check for exceptions in some camera operations.

Not all camera operations are documented to raise exceptions, but they
actually might do so depending on the hardware/drivers.
Check for exceptions in all functions that could porentially fail
and react appropriately.

Task-number: QTBUG-49134
Change-Id: I633ca7f2e3aeb6532e1c445735e62135f52cf25f
Reviewed-by: Christian Stromme <christian.stromme@theqtcompany.com>
This commit is contained in:
Yoann Lopes
2015-11-10 15:34:22 +01:00
parent 3b322323d0
commit b7880782b9
4 changed files with 61 additions and 2 deletions

View File

@@ -214,6 +214,8 @@ bool QAndroidCameraSession::open()
connect(m_camera, SIGNAL(pictureCaptured(QByteArray)), this, SLOT(onCameraPictureCaptured(QByteArray)));
connect(m_camera, SIGNAL(previewStarted()), this, SLOT(onCameraPreviewStarted()));
connect(m_camera, SIGNAL(previewStopped()), this, SLOT(onCameraPreviewStopped()));
connect(m_camera, &AndroidCamera::previewFailedToStart, this, &QAndroidCameraSession::onCameraPreviewFailedToStart);
connect(m_camera, &AndroidCamera::takePictureFailed, this, &QAndroidCameraSession::onCameraTakePictureFailed);
m_nativeOrientation = m_camera->getNativeOrientation();
@@ -554,6 +556,12 @@ void QAndroidCameraSession::cancelCapture()
m_captureCanceled = true;
}
void QAndroidCameraSession::onCameraTakePictureFailed()
{
emit imageCaptureError(m_currentImageCaptureId, QCameraImageCapture::ResourceError,
tr("Failed to capture image"));
}
void QAndroidCameraSession::onCameraPictureExposed()
{
if (m_captureCanceled)
@@ -646,6 +654,27 @@ void QAndroidCameraSession::onCameraPreviewStarted()
setReadyForCapture(true);
}
void QAndroidCameraSession::onCameraPreviewFailedToStart()
{
if (m_status == QCamera::StartingStatus) {
Q_EMIT error(QCamera::CameraError, tr("Camera preview failed to start."));
AndroidMultimediaUtils::enableOrientationListener(false);
m_camera->setPreviewSize(QSize());
m_camera->setPreviewTexture(0);
if (m_videoOutput) {
m_videoOutput->stop();
m_videoOutput->reset();
}
m_previewStarted = false;
m_status = QCamera::LoadedStatus;
emit statusChanged(m_status);
setReadyForCapture(false);
}
}
void QAndroidCameraSession::onCameraPreviewStopped()
{
if (m_status == QCamera::StoppingStatus) {

View File

@@ -112,11 +112,13 @@ private Q_SLOTS:
void onApplicationStateChanged(Qt::ApplicationState state);
void onCameraTakePictureFailed();
void onCameraPictureExposed();
void onCameraPictureCaptured(const QByteArray &data);
void onLastPreviewFrameFetched(const QByteArray &preview, int width, int height);
void onNewPreviewFrame(const QByteArray &frame, int width, int height);
void onCameraPreviewStarted();
void onCameraPreviewFailedToStart();
void onCameraPreviewStopped();
private:

View File

@@ -224,12 +224,15 @@ public:
Q_SIGNALS:
void previewSizeChanged();
void previewStarted();
void previewFailedToStart();
void previewStopped();
void autoFocusStarted();
void whiteBalanceChanged();
void takePictureFailed();
void lastPreviewFrameFetched(const QByteArray &preview, int width, int height);
};
@@ -245,9 +248,11 @@ AndroidCamera::AndroidCamera(AndroidCameraPrivate *d, QThread *worker)
connect(d, &AndroidCameraPrivate::previewSizeChanged, this, &AndroidCamera::previewSizeChanged);
connect(d, &AndroidCameraPrivate::previewStarted, this, &AndroidCamera::previewStarted);
connect(d, &AndroidCameraPrivate::previewFailedToStart, this, &AndroidCamera::previewFailedToStart);
connect(d, &AndroidCameraPrivate::previewStopped, this, &AndroidCamera::previewStopped);
connect(d, &AndroidCameraPrivate::autoFocusStarted, this, &AndroidCamera::autoFocusStarted);
connect(d, &AndroidCameraPrivate::whiteBalanceChanged, this, &AndroidCamera::whiteBalanceChanged);
connect(d, &AndroidCameraPrivate::takePictureFailed, this, &AndroidCamera::takePictureFailed);
connect(d, &AndroidCameraPrivate::lastPreviewFrameFetched, this, &AndroidCamera::lastPreviewFrameFetched);
}
@@ -1057,15 +1062,21 @@ void AndroidCameraPrivate::setFocusAreas(const QList<QRect> &areas)
void AndroidCameraPrivate::autoFocus()
{
QJNIEnvironmentPrivate env;
m_camera.callMethod<void>("autoFocus",
"(Landroid/hardware/Camera$AutoFocusCallback;)V",
m_cameraListener.object());
if (!exceptionCheckAndClear(env))
emit autoFocusStarted();
}
void AndroidCameraPrivate::cancelAutoFocus()
{
QJNIEnvironmentPrivate env;
m_camera.callMethod<void>("cancelAutoFocus");
exceptionCheckAndClear(env);
}
bool AndroidCameraPrivate::isAutoExposureLockSupported()
@@ -1314,25 +1325,40 @@ void AndroidCameraPrivate::setJpegQuality(int quality)
void AndroidCameraPrivate::startPreview()
{
QJNIEnvironmentPrivate env;
setupPreviewFrameCallback();
m_camera.callMethod<void>("startPreview");
if (exceptionCheckAndClear(env))
emit previewFailedToStart();
else
emit previewStarted();
}
void AndroidCameraPrivate::stopPreview()
{
QJNIEnvironmentPrivate env;
m_camera.callMethod<void>("stopPreview");
exceptionCheckAndClear(env);
emit previewStopped();
}
void AndroidCameraPrivate::takePicture()
{
QJNIEnvironmentPrivate env;
m_camera.callMethod<void>("takePicture", "(Landroid/hardware/Camera$ShutterCallback;"
"Landroid/hardware/Camera$PictureCallback;"
"Landroid/hardware/Camera$PictureCallback;)V",
m_cameraListener.object(),
jobject(0),
m_cameraListener.object());
if (exceptionCheckAndClear(env))
emit takePictureFailed();
}
void AndroidCameraPrivate::setupPreviewFrameCallback()

View File

@@ -168,6 +168,7 @@ public:
Q_SIGNALS:
void previewSizeChanged();
void previewStarted();
void previewFailedToStart();
void previewStopped();
void autoFocusStarted();
@@ -175,6 +176,7 @@ Q_SIGNALS:
void whiteBalanceChanged();
void takePictureFailed();
void pictureExposed();
void pictureCaptured(const QByteArray &data);
void lastPreviewFrameFetched(const QByteArray &preview, int width, int height);