diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp index 963952294c66f5f6f691e0fe0f38d5d0a01ae0d1..90d223c34cee22b4e6351ed304f1ac341b7474a5 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp @@ -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); diff --git a/src/plugins/android/src/wrappers/jni/androidcamera.cpp b/src/plugins/android/src/wrappers/jni/androidcamera.cpp index c917bf2b732787422a2e248d687cfdebfc880479..32fc4bbaf8f83627773d6e9280ed206af7cf9dcd 100644 --- a/src/plugins/android/src/wrappers/jni/androidcamera.cpp +++ b/src/plugins/android/src/wrappers/jni/androidcamera.cpp @@ -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, diff --git a/src/plugins/android/src/wrappers/jni/androidcamera.h b/src/plugins/android/src/wrappers/jni/androidcamera.h index 2ea69b7e3ac28563fe95546221d06c87c9925723..010f089fb9cfb429a5285684b859c6be3a145670 100644 --- a/src/plugins/android/src/wrappers/jni/androidcamera.h +++ b/src/plugins/android/src/wrappers/jni/androidcamera.h @@ -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();