Commit 6af9a170 authored by dogmaphobic's avatar dogmaphobic

More Android work...

parent db135056
......@@ -60,6 +60,7 @@ public class UsbDeviceJNI extends QtActivity
// USED TO DETECT WHEN A DEVICE HAS BEEN UNPLUGGED
private BroadcastReceiver m_UsbReceiver = null;
private final static ExecutorService m_Executor = Executors.newSingleThreadExecutor();
private static final String TAG = "QGC_UsbDeviceJNI";
private final static UsbIoManager.Listener m_Listener =
new UsbIoManager.Listener()
......@@ -67,6 +68,7 @@ public class UsbDeviceJNI extends QtActivity
@Override
public void onRunError(Exception eA, int userDataA)
{
Log.e(TAG, "onRunError Exception");
nativeDeviceException(userDataA, eA.getMessage());
}
......@@ -77,7 +79,6 @@ public class UsbDeviceJNI extends QtActivity
}
};
private static final String TAG = "QGC_UsbDeviceJNI";
// NATIVE C++ FUNCTION THAT WILL BE CALLED IF THE DEVICE IS UNPLUGGED
private static native void nativeDeviceHasDisconnected(int userDataA);
......@@ -120,7 +121,6 @@ public class UsbDeviceJNI extends QtActivity
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// List all available devices that are not already open. It returns the serial port info
......
......@@ -54,8 +54,8 @@ QT_BEGIN_NAMESPACE
#define BAD_PORT 0
static const char V_jniClassName[] {"org/qgroundcontrol/qgchelper/UsbDeviceJNI"};
static const char V_TAG[] {"QGC_QSerialPort"};
static const char kJniClassName[] {"org/qgroundcontrol/qgchelper/UsbDeviceJNI"};
static const char kJTag[] {"QGC_QSerialPort"};
static void jniDeviceHasDisconnected(JNIEnv *envA, jobject thizA, jint userDataA)
{
......@@ -91,6 +91,15 @@ static void jniDeviceException(JNIEnv *envA, jobject thizA, jint userDataA, jstr
}
}
void cleanJavaException()
{
QAndroidJniEnvironment env;
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
}
QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q)
: QSerialPortPrivateData(q)
, descriptor(-1)
......@@ -109,57 +118,75 @@ QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q)
bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
{
rwMode = mode;
__android_log_print(ANDROID_LOG_INFO, V_TAG, "Opening %s", systemLocation.toLatin1().data());
__android_log_print(ANDROID_LOG_INFO, kJTag, "Opening %s", systemLocation.toLatin1().data());
__android_log_print(ANDROID_LOG_INFO, kJTag, "Calling Java Open");
QAndroidJniObject jnameL = QAndroidJniObject::fromString(systemLocation);
cleanJavaException();
deviceId = QAndroidJniObject::callStaticMethod<jint>(
kJniClassName,
"open",
"(Ljava/lang/String;I)I",
jnameL.object<jstring>(),
(jint)this);
cleanJavaException();
isReadStopped = false;
if (deviceId == BAD_PORT)
{
__android_log_print(ANDROID_LOG_ERROR, kJTag, "Error opening %s", systemLocation.toLatin1().data());
q_ptr->setError(QSerialPort::DeviceNotFoundError);
return false;
}
if (!hasRegisteredFunctions)
{
__android_log_print(ANDROID_LOG_INFO, kJTag, "Registering Native Functions");
// REGISTER THE C++ FUNCTION WITH JNI
QAndroidJniEnvironment envL;
JNINativeMethod methodsL[] {
JNINativeMethod javaMethods[] {
{"nativeDeviceHasDisconnected", "(I)V", reinterpret_cast<void *>(jniDeviceHasDisconnected)},
{"nativeDeviceNewData", "(I[B)V", reinterpret_cast<void *>(jniDeviceNewData)},
{"nativeDeviceException", "(ILjava/lang/String;)V", reinterpret_cast<void *>(jniDeviceException)}
};
QAndroidJniObject javaClassL(V_jniClassName);
jclass objectClassL = envL->GetObjectClass(javaClassL.object<jobject>());
jint valL = envL->RegisterNatives(objectClassL, methodsL, sizeof(methodsL) / sizeof(JNINativeMethod));
envL->DeleteLocalRef(objectClassL);
QAndroidJniEnvironment jniEnv;
if (jniEnv->ExceptionCheck()) {
jniEnv->ExceptionDescribe();
jniEnv->ExceptionClear();
}
QAndroidJniObject javaClass(kJniClassName);
if(!javaClass.isValid()) {
__android_log_print(ANDROID_LOG_ERROR, kJTag, "Java class %s not valid", kJniClassName);
return false;
}
jclass objectClass = jniEnv->GetObjectClass(javaClass.object<jobject>());
jint val = jniEnv->RegisterNatives(objectClass, javaMethods, sizeof(javaMethods) / sizeof(javaMethods[0]));
jniEnv->DeleteLocalRef(objectClass);
hasRegisteredFunctions = true;
__android_log_print(ANDROID_LOG_INFO, kJTag, "Native Functions Registered");
if (envL->ExceptionCheck())
envL->ExceptionClear();
if (jniEnv->ExceptionCheck()) {
jniEnv->ExceptionDescribe();
jniEnv->ExceptionClear();
}
if(valL < 0) {
__android_log_print(ANDROID_LOG_ERROR, V_TAG, "Error registering methods");
if(val < 0) {
__android_log_print(ANDROID_LOG_ERROR, kJTag, "Error registering methods");
q_ptr->setError(QSerialPort::OpenError);
return false;
}
}
QAndroidJniObject jnameL = QAndroidJniObject::fromString(systemLocation);
deviceId = QAndroidJniObject::callStaticMethod<jint>(
V_jniClassName,
"open",
"(Ljava/lang/String;I)I",
jnameL.object<jstring>(),
(jint)this);
isReadStopped = false;
if (deviceId == BAD_PORT)
{
__android_log_print(ANDROID_LOG_ERROR, V_TAG, "Error opening %s", systemLocation.toLatin1().data());
q_ptr->setError(QSerialPort::DeviceNotFoundError);
return false;
}
__android_log_print(ANDROID_LOG_INFO, kJTag, "Calling Java getDeviceHandle");
cleanJavaException();
descriptor = QAndroidJniObject::callStaticMethod<jint>(
V_jniClassName,
kJniClassName,
"getDeviceHandle",
"(I)I",
deviceId);
cleanJavaException();
if (rwMode == QIODevice::WriteOnly)
stopReadThread();
......@@ -172,12 +199,14 @@ void QSerialPortPrivate::close()
if (deviceId == BAD_PORT)
return;
__android_log_print(ANDROID_LOG_INFO, V_TAG, "Closing %s", systemLocation.toLatin1().data());
__android_log_print(ANDROID_LOG_INFO, kJTag, "Closing %s", systemLocation.toLatin1().data());
cleanJavaException();
jboolean resultL = QAndroidJniObject::callStaticMethod<jboolean>(
V_jniClassName,
kJniClassName,
"close",
"(I)Z",
deviceId);
cleanJavaException();
descriptor = -1;
isCustomBaudRateSupported = false;
......@@ -196,14 +225,17 @@ bool QSerialPortPrivate::setParameters(int baudRateA, int dataBitsA, int stopBit
return false;
}
jboolean resultL = QAndroidJniObject::callStaticMethod<jboolean>(V_jniClassName,
"setParameters",
"(IIIII)Z",
deviceId,
baudRateA,
dataBitsA,
stopBitsA,
parityA);
cleanJavaException();
jboolean resultL = QAndroidJniObject::callStaticMethod<jboolean>(
kJniClassName,
"setParameters",
"(IIIII)Z",
deviceId,
baudRateA,
dataBitsA,
stopBitsA,
parityA);
cleanJavaException();
if(resultL)
{
......@@ -223,11 +255,13 @@ void QSerialPortPrivate::stopReadThread()
{
if (isReadStopped)
return;
QAndroidJniObject::callStaticMethod<void>(V_jniClassName,
"stopIoManager",
"(I)V",
deviceId);
cleanJavaException();
QAndroidJniObject::callStaticMethod<void>(
kJniClassName,
"stopIoManager",
"(I)V",
deviceId);
cleanJavaException();
isReadStopped = true;
}
......@@ -237,26 +271,21 @@ void QSerialPortPrivate::startReadThread()
{
if (!isReadStopped)
return;
QAndroidJniObject::callStaticMethod<void>(V_jniClassName,
"startIoManager",
"(I)V",
deviceId);
cleanJavaException();
QAndroidJniObject::callStaticMethod<void>(
kJniClassName,
"startIoManager",
"(I)V",
deviceId);
cleanJavaException();
isReadStopped = false;
}
QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals()
{
return QSerialPort::NoSignal;
}
bool QSerialPortPrivate::setDataTerminalReady(bool set)
{
if (deviceId == BAD_PORT)
......@@ -264,17 +293,17 @@ bool QSerialPortPrivate::setDataTerminalReady(bool set)
q_ptr->setError(QSerialPort::NotOpenError);
return false;
}
return QAndroidJniObject::callStaticMethod<jboolean>(V_jniClassName,
"setDataTerminalReady",
"(IZ)Z",
deviceId,
set);
cleanJavaException();
bool res = QAndroidJniObject::callStaticMethod<jboolean>(
kJniClassName,
"setDataTerminalReady",
"(IZ)Z",
deviceId,
set);
cleanJavaException();
return res;
}
bool QSerialPortPrivate::setRequestToSend(bool set)
{
if (deviceId == BAD_PORT)
......@@ -282,25 +311,22 @@ bool QSerialPortPrivate::setRequestToSend(bool set)
q_ptr->setError(QSerialPort::NotOpenError);
return false;
}
return QAndroidJniObject::callStaticMethod<jboolean>(V_jniClassName,
"setRequestToSend",
"(IZ)Z",
deviceId,
set);
cleanJavaException();
bool res = QAndroidJniObject::callStaticMethod<jboolean>(
kJniClassName,
"setRequestToSend",
"(IZ)Z",
deviceId,
set);
cleanJavaException();
return res;
}
bool QSerialPortPrivate::flush()
{
return writeDataOneShot();
}
bool QSerialPortPrivate::clear(QSerialPort::Directions directions)
{
if (deviceId == BAD_PORT)
......@@ -323,16 +349,18 @@ bool QSerialPortPrivate::clear(QSerialPort::Directions directions)
outputL = true;
}
return QAndroidJniObject::callStaticMethod<jboolean>(V_jniClassName,
"purgeBuffers",
"(IZZ)Z",
deviceId,
inputL,
outputL);
}
cleanJavaException();
bool res = QAndroidJniObject::callStaticMethod<jboolean>(
kJniClassName,
"purgeBuffers",
"(IZZ)Z",
deviceId,
inputL,
outputL);
cleanJavaException();
return res;
}
bool QSerialPortPrivate::sendBreak(int duration)
{
......@@ -340,26 +368,17 @@ bool QSerialPortPrivate::sendBreak(int duration)
return true;
}
bool QSerialPortPrivate::setBreakEnabled(bool set)
{
Q_UNUSED(set);
return true;
}
void QSerialPortPrivate::startWriting()
{
writeDataOneShot();
}
bool QSerialPortPrivate::waitForReadyRead(int msecs)
{
int origL = readBuffer.size();
......@@ -378,41 +397,26 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs)
return false;
}
bool QSerialPortPrivate::waitForBytesWritten(int msecs)
{
internalWriteTimeoutMsec = msecs;
bool retL = writeDataOneShot();
internalWriteTimeoutMsec = 0;
return retL;
}
bool QSerialPortPrivate::setBaudRate()
{
setBaudRate(inputBaudRate, QSerialPort::AllDirections);
return true;
}
bool QSerialPortPrivate::setBaudRate(qint32 baudRate, QSerialPort::Directions directions)
{
Q_UNUSED(directions);
return setParameters(baudRate, jniDataBits, jniStopBits, jniParity);
}
bool QSerialPortPrivate::setDataBits(QSerialPort::DataBits dataBits)
{
int numBitsL = 8;
......@@ -436,17 +440,12 @@ bool QSerialPortPrivate::setDataBits(QSerialPort::DataBits dataBits)
numBitsL = 8;
break;
}
return setParameters(inputBaudRate, numBitsL, jniStopBits, jniParity);
}
bool QSerialPortPrivate::setParity(QSerialPort::Parity parity)
{
int parL = 0;
switch (parity)
{
case QSerialPort::SpaceParity:
......@@ -470,17 +469,12 @@ bool QSerialPortPrivate::setParity(QSerialPort::Parity parity)
parL = 0;
break;
}
return setParameters(inputBaudRate, jniDataBits, jniStopBits, parL);
}
bool QSerialPortPrivate::setStopBits(QSerialPort::StopBits stopBits)
{
int stopL = 1;
switch (stopBits)
{
case QSerialPort::TwoStop:
......@@ -496,29 +490,21 @@ bool QSerialPortPrivate::setStopBits(QSerialPort::StopBits stopBits)
stopL = 1;
break;
}
return setParameters(inputBaudRate, jniDataBits, stopL, jniParity);
}
bool QSerialPortPrivate::setFlowControl(QSerialPort::FlowControl flowControl)
{
Q_UNUSED(flowControl);
return true;
}
bool QSerialPortPrivate::setDataErrorPolicy(QSerialPort::DataErrorPolicy policy)
{
this->policy = policy;
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void QSerialPortPrivate::newDataArrived(char *bytesA, int lengthA)
{
......@@ -550,8 +536,6 @@ void QSerialPortPrivate::exceptionArrived(QString strA)
q_ptr->setErrorString(strA);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool QSerialPortPrivate::writeDataOneShot()
{
......@@ -580,8 +564,6 @@ bool QSerialPortPrivate::writeDataOneShot()
return (pendingBytesWritten < 0)? false: true;
}
QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const
{
QSerialPort::SerialPortError error;
......@@ -611,8 +593,6 @@ QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const
return error;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
qint64 QSerialPortPrivate::writeToPort(const char *data, qint64 maxSize)
{
......@@ -622,32 +602,30 @@ qint64 QSerialPortPrivate::writeToPort(const char *data, qint64 maxSize)
return 0;
}
QAndroidJniEnvironment envL;
jbyteArray jarrayL = envL->NewByteArray(maxSize);
envL->SetByteArrayRegion(jarrayL, 0, maxSize, (jbyte *)data);
int resultL = QAndroidJniObject::callStaticMethod<jint>(V_jniClassName,
"write",
"(I[BI)I",
deviceId,
jarrayL,
internalWriteTimeoutMsec);
if (envL->ExceptionCheck())
QAndroidJniEnvironment jniEnv;
jbyteArray jarrayL = jniEnv->NewByteArray(maxSize);
jniEnv->SetByteArrayRegion(jarrayL, 0, maxSize, (jbyte *)data);
if (jniEnv->ExceptionCheck())
jniEnv->ExceptionClear();
int resultL = QAndroidJniObject::callStaticMethod<jint>(
kJniClassName,
"write",
"(I[BI)I",
deviceId,
jarrayL,
internalWriteTimeoutMsec);
if (jniEnv->ExceptionCheck())
{
envL->ExceptionClear();
jniEnv->ExceptionClear();
q_ptr->setErrorString(QStringLiteral("Writing to the device threw an exception"));
envL->DeleteLocalRef(jarrayL);
jniEnv->DeleteLocalRef(jarrayL);
return 0;
}
envL->DeleteLocalRef(jarrayL);
jniEnv->DeleteLocalRef(jarrayL);
return resultL;
}
static inline bool evenParity(quint8 c)
{
c ^= c >> 4; //(c7 ^ c3)(c6 ^ c2)(c5 ^ c1)(c4 ^ c0)
......@@ -803,42 +781,27 @@ static const BaudRateMap createStandardBaudRateMap()
return baudRateMap;
}
static const BaudRateMap& standardBaudRateMap()
{
static const BaudRateMap baudRateMap = createStandardBaudRateMap();
return baudRateMap;
}
qint32 QSerialPortPrivate::baudRateFromSetting(qint32 setting)
{
return standardBaudRateMap().key(setting);
}
qint32 QSerialPortPrivate::settingFromBaudRate(qint32 baudRate)
{
return standardBaudRateMap().value(baudRate);
}
QList<qint32> QSerialPortPrivate::standardBaudRates()
{
return standardBaudRateMap().keys();
}
QSerialPort::Handle QSerialPort::handle() const
{
Q_D(const QSerialPort);
......
......@@ -48,6 +48,8 @@ QT_BEGIN_NAMESPACE
static const char V_jniClassName[] {"org/qgroundcontrol/qgchelper/UsbDeviceJNI"};
static const char V_TAG[] {"QGC_QSerialPortInfo"};
extern void cleanJavaException();
QList<QSerialPortInfo> availablePortsByFiltersOfDevices(bool &ok)
{
QList<QSerialPortInfo> serialPortInfoList;
......@@ -117,22 +119,26 @@ QList<qint32> QSerialPortInfo::standardBaudRates()
bool QSerialPortInfo::isBusy() const
{
QAndroidJniObject jstrL = QAndroidJniObject::fromString(d_ptr->portName);
cleanJavaException();
jboolean resultL = QAndroidJniObject::callStaticMethod<jboolean>(
V_jniClassName,
"isDeviceNameOpen",
"(Ljava/lang/String;)Z",
jstrL.object<jstring>());
cleanJavaException();
return resultL;
}
bool QSerialPortInfo::isValid() const
{
QAndroidJniObject jstrL = QAndroidJniObject::fromString(d_ptr->portName);
cleanJavaException();
jboolean resultL = QAndroidJniObject::callStaticMethod<jboolean>(
V_jniClassName,
"isDeviceNameValid",
"(Ljava/lang/String;)Z",
jstrL.object<jstring>());
cleanJavaException();
return resultL;
}
......
......@@ -104,7 +104,9 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) :
_app = this;
// This prevents usage of QQuickWidget to fail since it doesn't support native widget siblings
#ifndef __android__
setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
#endif
#ifdef QT_DEBUG
// First thing we want to do is set up the qtlogging.ini file. If it doesn't already exist we copy
......
......@@ -217,10 +217,10 @@ void QGCFileDialog::_validate(Options& options)
Q_ASSERT(qgcApp());
Q_ASSERT_X(QThread::currentThread() == qgcApp()->thread(), "Threading issue", "QGCFileDialog can only be called from main thread");
#ifndef __android__
// On OSX native dialog can hang so we always use Qt dialogs
options |= DontUseNativeDialog;
#endif
if (MainWindow::instance()) {
MainWindow::instance()->hideSplashScreen();
}
......
......@@ -183,8 +183,10 @@ MainWindow::MainWindow(QSplashScreen* splashScreen)
// Qt 4 on Ubuntu does place the native menubar correctly so on Linux we revert back to in-window menu bar.
// TODO: Check that this is still necessary on Qt5 on Ubuntu
#ifdef Q_OS_LINUX
#ifndef __android__
menuBar()->setNativeMenuBar(false);
#endif
#endif
#ifdef UNITTEST_BUILD
QAction* qmlTestAction = new QAction("Test QML palette and controls", NULL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment