From 749cdff5289412780f0bb8e351cb140ba64d85ce Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Thu, 22 May 2014 12:14:11 +0200 Subject: Fix crash on S4 when running Satellite and Position updates concurrently This was caused due to unsynchronized access of data between two threads. The Java satellite updates were sent before the receiving Qt thread could finish its regular startup. As a consequence the received updates could not be mapped to a receiving C++ class. This patch synchronizes the startup and setup of the two threads and ensures that the relvant data setup on the C++ side is done before the update thread is started. In addition some minor debug helpers were added for future references. Task-number: QTBUG-39082 Change-Id: I1f24ddfcef038fa000801ddb6a3ea0959370f0d3 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../qt5/android/positioning/QtPositioning.java | 30 +++++++++++++++------- .../position/android/src/jnipositioning.cpp | 4 +-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java b/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java index f5725813..f2babd08 100644 --- a/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java +++ b/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java @@ -187,17 +187,18 @@ public class QtPositioning implements LocationListener try { boolean exceptionOccurred = false; QtPositioning positioningListener = new QtPositioning(); - positioningListener.setActiveLooper(true); positioningListener.nativeClassReference = androidClassKey; positioningListener.expectedProviders = locationProvider; positioningListener.isSatelliteUpdate = false; + //start update thread + positioningListener.setActiveLooper(true); if (updateInterval == 0) updateInterval = 1000; //don't update more often than once per second positioningListener.updateIntervalTime = updateInterval; if ((locationProvider & QT_GPS_PROVIDER) > 0) { - Log.d(TAG, "Regular updates using GPS"); + Log.d(TAG, "Regular updates using GPS " + updateInterval); try { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, updateInterval, 0, @@ -210,7 +211,7 @@ public class QtPositioning implements LocationListener } if ((locationProvider & QT_NETWORK_PROVIDER) > 0) { - Log.d(TAG, "Regular updates using network"); + Log.d(TAG, "Regular updates using network " + updateInterval); try { locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, updateInterval, 0, @@ -263,11 +264,12 @@ public class QtPositioning implements LocationListener try { boolean exceptionOccurred = false; QtPositioning positioningListener = new QtPositioning(); - positioningListener.setActiveLooper(true); positioningListener.nativeClassReference = androidClassKey; positioningListener.isSingleUpdate = true; positioningListener.expectedProviders = locationProvider; positioningListener.isSatelliteUpdate = false; + //start update thread + positioningListener.setActiveLooper(true); if ((locationProvider & QT_GPS_PROVIDER) > 0) { Log.d(TAG, "Single update using GPS"); @@ -321,10 +323,11 @@ public class QtPositioning implements LocationListener boolean exceptionOccurred = false; QtPositioning positioningListener = new QtPositioning(); positioningListener.isSatelliteUpdate = true; - positioningListener.setActiveLooper(true); positioningListener.nativeClassReference = androidClassKey; positioningListener.expectedProviders = 1; //always satellite provider positioningListener.isSingleUpdate = isSingleRequest; + //start update thread + positioningListener.setActiveLooper(true); if (updateInterval == 0) updateInterval = 1000; //don't update more often than once per second @@ -385,9 +388,14 @@ public class QtPositioning implements LocationListener if (isSatelliteUpdate) looperThread.isSatelliteListener(true); + long start = System.currentTimeMillis(); looperThread.start(); + + //busy wait but lasts ~20-30 ms only while (!looperThread.isReady()); - Thread.sleep(1000); + + long stop = System.currentTimeMillis(); + Log.d(TAG, "Looper Thread startup time in ms: " + (stop-start)); } else { looperThread.quitLooper(); } @@ -411,7 +419,6 @@ public class QtPositioning implements LocationListener { Looper.prepare(); Handler handler = new Handler(); - looperRunning = true; if (isSatelliteLooper) { try { @@ -422,8 +429,13 @@ public class QtPositioning implements LocationListener } posLooper = Looper.myLooper(); + synchronized (this) { + looperRunning = true; + } Looper.loop(); - looperRunning = false; + synchronized (this) { + looperRunning = false; + } } public void quitLooper() @@ -433,7 +445,7 @@ public class QtPositioning implements LocationListener looper().quit(); } - public boolean isReady() + public synchronized boolean isReady() { return looperRunning; } diff --git a/src/plugins/position/android/src/jnipositioning.cpp b/src/plugins/position/android/src/jnipositioning.cpp index afae1c8e..d3cce65b 100644 --- a/src/plugins/position/android/src/jnipositioning.cpp +++ b/src/plugins/position/android/src/jnipositioning.cpp @@ -459,7 +459,7 @@ static void positionUpdated(JNIEnv *env, jobject /*thiz*/, jobject location, jin QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey); if (!source) { - qFatal("positionUpdated: source == 0"); + qWarning("positionUpdated: source == 0"); return; } @@ -479,7 +479,7 @@ static void locationProvidersDisabled(JNIEnv *env, jobject /*thiz*/, jint androi if (!source) source = AndroidPositioning::idToSatSource()->value(androidClassKey); if (!source) { - qFatal("locationProvidersDisabled: source == 0"); + qWarning("locationProvidersDisabled: source == 0"); return; } -- cgit v1.2.1