Android: Make sure we check and clear exceptions from the camera.
In several places we where ignoring the fact that we might get an exception from the camera code on Android. Failing to clear them will cause the application to to terminate. Task-number: QTBUG-39425 Change-Id: Idfe40e1749f54d551d37dae25912d9ddbc3da01e Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
This commit is contained in:
committed by
Christian Stromme
parent
389d66b3ed
commit
a7d10a265a
@@ -331,11 +331,12 @@ bool QAndroidCameraSession::startPreview()
|
||||
if (m_previewStarted)
|
||||
return true;
|
||||
|
||||
if (m_videoOutput->isReady())
|
||||
m_camera->setPreviewTexture(m_videoOutput->surfaceTexture());
|
||||
else
|
||||
if (!m_videoOutput->isReady())
|
||||
return true; // delay starting until the video output is ready
|
||||
|
||||
if (!m_camera->setPreviewTexture(m_videoOutput->surfaceTexture()))
|
||||
return false;
|
||||
|
||||
m_status = QCamera::StartingStatus;
|
||||
emit statusChanged(m_status);
|
||||
|
||||
|
||||
@@ -56,6 +56,19 @@ static QMutex g_cameraMapMutex;
|
||||
typedef QMap<int, AndroidCamera *> CameraMap;
|
||||
Q_GLOBAL_STATIC(CameraMap, g_cameraMap)
|
||||
|
||||
static inline bool exceptionCheckAndClear(JNIEnv *env)
|
||||
{
|
||||
if (Q_UNLIKELY(env->ExceptionCheck())) {
|
||||
#ifdef QT_DEBUG
|
||||
env->ExceptionDescribe();
|
||||
#endif // QT_DEBUG
|
||||
env->ExceptionClear();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static QRect areaToRect(jobject areaObj)
|
||||
{
|
||||
QJNIObjectPrivate area(areaObj);
|
||||
@@ -132,9 +145,9 @@ public:
|
||||
Q_INVOKABLE bool init(int cameraId);
|
||||
|
||||
Q_INVOKABLE void release();
|
||||
Q_INVOKABLE void lock();
|
||||
Q_INVOKABLE void unlock();
|
||||
Q_INVOKABLE void reconnect();
|
||||
Q_INVOKABLE bool lock();
|
||||
Q_INVOKABLE bool unlock();
|
||||
Q_INVOKABLE bool reconnect();
|
||||
|
||||
Q_INVOKABLE AndroidCamera::CameraFacing getFacing();
|
||||
Q_INVOKABLE int getNativeOrientation();
|
||||
@@ -147,7 +160,7 @@ public:
|
||||
|
||||
Q_INVOKABLE QSize previewSize() const { return m_previewSize; }
|
||||
Q_INVOKABLE void updatePreviewSize();
|
||||
Q_INVOKABLE void setPreviewTexture(void *surfaceTexture);
|
||||
Q_INVOKABLE bool setPreviewTexture(void *surfaceTexture);
|
||||
|
||||
Q_INVOKABLE bool isZoomSupported();
|
||||
Q_INVOKABLE int getMaxZoom();
|
||||
@@ -266,7 +279,7 @@ AndroidCamera *AndroidCamera::open(int cameraId)
|
||||
worker->start();
|
||||
d->moveToThread(worker);
|
||||
connect(worker, &QThread::finished, d, &AndroidCameraPrivate::deleteLater);
|
||||
bool ok = false;
|
||||
bool ok = true;
|
||||
QMetaObject::invokeMethod(d, "init", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ok), Q_ARG(int, cameraId));
|
||||
if (!ok) {
|
||||
worker->quit();
|
||||
@@ -289,22 +302,28 @@ int AndroidCamera::cameraId() const
|
||||
return d->m_cameraId;
|
||||
}
|
||||
|
||||
void AndroidCamera::lock()
|
||||
bool AndroidCamera::lock()
|
||||
{
|
||||
Q_D(AndroidCamera);
|
||||
QMetaObject::invokeMethod(d, "lock", Qt::BlockingQueuedConnection);
|
||||
bool ok = true;
|
||||
QMetaObject::invokeMethod(d, "lock", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ok));
|
||||
return ok;
|
||||
}
|
||||
|
||||
void AndroidCamera::unlock()
|
||||
bool AndroidCamera::unlock()
|
||||
{
|
||||
Q_D(AndroidCamera);
|
||||
QMetaObject::invokeMethod(d, "unlock", Qt::BlockingQueuedConnection);
|
||||
bool ok = true;
|
||||
QMetaObject::invokeMethod(d, "unlock", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ok));
|
||||
return ok;
|
||||
}
|
||||
|
||||
void AndroidCamera::reconnect()
|
||||
bool AndroidCamera::reconnect()
|
||||
{
|
||||
Q_D(AndroidCamera);
|
||||
QMetaObject::invokeMethod(d, "reconnect");
|
||||
bool ok = true;
|
||||
QMetaObject::invokeMethod(d, "reconnect", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ok));
|
||||
return ok;
|
||||
}
|
||||
|
||||
void AndroidCamera::release()
|
||||
@@ -368,13 +387,16 @@ void AndroidCamera::setPreviewSize(const QSize &size)
|
||||
QMetaObject::invokeMethod(d, "updatePreviewSize");
|
||||
}
|
||||
|
||||
void AndroidCamera::setPreviewTexture(AndroidSurfaceTexture *surfaceTexture)
|
||||
bool AndroidCamera::setPreviewTexture(AndroidSurfaceTexture *surfaceTexture)
|
||||
{
|
||||
Q_D(AndroidCamera);
|
||||
bool ok = true;
|
||||
QMetaObject::invokeMethod(d,
|
||||
"setPreviewTexture",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, ok),
|
||||
Q_ARG(void *, surfaceTexture ? surfaceTexture->surfaceTexture() : 0));
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool AndroidCamera::isZoomSupported()
|
||||
@@ -698,12 +720,12 @@ AndroidCameraPrivate::~AndroidCameraPrivate()
|
||||
bool AndroidCameraPrivate::init(int cameraId)
|
||||
{
|
||||
m_cameraId = cameraId;
|
||||
QJNIEnvironmentPrivate env;
|
||||
m_camera = QJNIObjectPrivate::callStaticObjectMethod("android/hardware/Camera",
|
||||
"open",
|
||||
"(I)Landroid/hardware/Camera;",
|
||||
cameraId);
|
||||
|
||||
if (!m_camera.isValid())
|
||||
if (exceptionCheckAndClear(env) || !m_camera.isValid())
|
||||
return false;
|
||||
|
||||
m_cameraListener = QJNIObjectPrivate(g_qtCameraListenerClass, "(I)V", m_cameraId);
|
||||
@@ -731,26 +753,25 @@ void AndroidCameraPrivate::release()
|
||||
m_camera.callMethod<void>("release");
|
||||
}
|
||||
|
||||
void AndroidCameraPrivate::lock()
|
||||
bool AndroidCameraPrivate::lock()
|
||||
{
|
||||
QJNIEnvironmentPrivate env;
|
||||
m_camera.callMethod<void>("lock");
|
||||
return !exceptionCheckAndClear(env);
|
||||
}
|
||||
|
||||
void AndroidCameraPrivate::unlock()
|
||||
bool AndroidCameraPrivate::unlock()
|
||||
{
|
||||
QJNIEnvironmentPrivate env;
|
||||
m_camera.callMethod<void>("unlock");
|
||||
return !exceptionCheckAndClear(env);
|
||||
}
|
||||
|
||||
void AndroidCameraPrivate::reconnect()
|
||||
bool AndroidCameraPrivate::reconnect()
|
||||
{
|
||||
QJNIEnvironmentPrivate env;
|
||||
m_camera.callMethod<void>("reconnect");
|
||||
if (env->ExceptionCheck()) {
|
||||
#ifdef QT_DEBUG
|
||||
env->ExceptionDescribe();
|
||||
#endif // QT_DEBUG
|
||||
env->ExceptionDescribe();
|
||||
}
|
||||
return !exceptionCheckAndClear(env);
|
||||
}
|
||||
|
||||
AndroidCamera::CameraFacing AndroidCameraPrivate::getFacing()
|
||||
@@ -832,11 +853,13 @@ void AndroidCameraPrivate::updatePreviewSize()
|
||||
emit previewSizeChanged();
|
||||
}
|
||||
|
||||
void AndroidCameraPrivate::setPreviewTexture(void *surfaceTexture)
|
||||
bool AndroidCameraPrivate::setPreviewTexture(void *surfaceTexture)
|
||||
{
|
||||
QJNIEnvironmentPrivate env;
|
||||
m_camera.callMethod<void>("setPreviewTexture",
|
||||
"(Landroid/graphics/SurfaceTexture;)V",
|
||||
static_cast<jobject>(surfaceTexture));
|
||||
return !exceptionCheckAndClear(env);
|
||||
}
|
||||
|
||||
bool AndroidCameraPrivate::isZoomSupported()
|
||||
@@ -1020,8 +1043,7 @@ void AndroidCameraPrivate::setFocusAreas(const QList<QRect> &areas)
|
||||
arrayList.callMethod<jboolean>("add",
|
||||
"(Ljava/lang/Object;)Z",
|
||||
rectToArea(areas.at(i)).object());
|
||||
if (env->ExceptionCheck())
|
||||
env->ExceptionClear();
|
||||
exceptionCheckAndClear(env);
|
||||
}
|
||||
list = arrayList;
|
||||
}
|
||||
@@ -1347,9 +1369,11 @@ void AndroidCameraPrivate::fetchLastPreviewFrame()
|
||||
|
||||
void AndroidCameraPrivate::applyParameters()
|
||||
{
|
||||
QJNIEnvironmentPrivate env;
|
||||
m_camera.callMethod<void>("setParameters",
|
||||
"(Landroid/hardware/Camera$Parameters;)V",
|
||||
m_parameters.object());
|
||||
exceptionCheckAndClear(env);
|
||||
}
|
||||
|
||||
QStringList AndroidCameraPrivate::callParametersStringListMethod(const QByteArray &methodName)
|
||||
@@ -1386,10 +1410,8 @@ static JNINativeMethod methods[] = {
|
||||
bool AndroidCamera::initJNI(JNIEnv *env)
|
||||
{
|
||||
jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtCameraListener");
|
||||
if (env->ExceptionCheck())
|
||||
env->ExceptionClear();
|
||||
|
||||
if (clazz) {
|
||||
if (!exceptionCheckAndClear(env) && clazz) {
|
||||
g_qtCameraListenerClass = static_cast<jclass>(env->NewGlobalRef(clazz));
|
||||
if (env->RegisterNatives(g_qtCameraListenerClass,
|
||||
methods,
|
||||
|
||||
@@ -90,9 +90,9 @@ public:
|
||||
|
||||
int cameraId() const;
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
void reconnect();
|
||||
bool lock();
|
||||
bool unlock();
|
||||
bool reconnect();
|
||||
void release();
|
||||
|
||||
CameraFacing getFacing();
|
||||
@@ -106,7 +106,7 @@ public:
|
||||
|
||||
QSize previewSize() const;
|
||||
void setPreviewSize(const QSize &size);
|
||||
void setPreviewTexture(AndroidSurfaceTexture *surfaceTexture);
|
||||
bool setPreviewTexture(AndroidSurfaceTexture *surfaceTexture);
|
||||
|
||||
bool isZoomSupported();
|
||||
int getMaxZoom();
|
||||
|
||||
Reference in New Issue
Block a user