summaryrefslogtreecommitdiffstats
path: root/core/jni
diff options
context:
space:
mode:
authorMike Lockwood <lockwood@android.com>2009-08-06 09:26:02 -0400
committerMike Lockwood <lockwood@android.com>2009-08-06 15:05:07 -0400
commitb16e7800be4f879135f239f1f8f586f3712df01e (patch)
treed3c41d32ac4341d66d9e042612237c13ab49e879 /core/jni
parentd4f09592f721e6358fdadbdf363f034f842f860d (diff)
downloadframeworks_base-b16e7800be4f879135f239f1f8f586f3712df01e.zip
frameworks_base-b16e7800be4f879135f239f1f8f586f3712df01e.tar.gz
frameworks_base-b16e7800be4f879135f239f1f8f586f3712df01e.tar.bz2
gps: Add GpsStatus.NmeaListener interface for receiving NMEA sentences.
NMEA sentences are passed from the GPS engine to the GpsLocationProvider. They are then sent via the IGpsStatusListener binder interface to clients using the same path as the other GPS status information. Signed-off-by: Mike Lockwood <lockwood@android.com>
Diffstat (limited to 'core/jni')
-rwxr-xr-xcore/jni/android_location_GpsLocationProvider.cpp76
1 files changed, 72 insertions, 4 deletions
diff --git a/core/jni/android_location_GpsLocationProvider.cpp b/core/jni/android_location_GpsLocationProvider.cpp
index bf0bd65..90a0487 100755
--- a/core/jni/android_location_GpsLocationProvider.cpp
+++ b/core/jni/android_location_GpsLocationProvider.cpp
@@ -32,6 +32,7 @@ static jmethodID method_reportLocation;
static jmethodID method_reportStatus;
static jmethodID method_reportSvStatus;
static jmethodID method_reportAGpsStatus;
+static jmethodID method_reportNmea;
static jmethodID method_xtraDownloadRequest;
static const GpsInterface* sGpsInterface = NULL;
@@ -44,12 +45,23 @@ static GpsStatus sGpsStatus;
static GpsSvStatus sGpsSvStatus;
static AGpsStatus sAGpsStatus;
+// buffer for NMEA data
+#define NMEA_SENTENCE_LENGTH 100
+#define NMEA_SENTENCE_COUNT 40
+struct NmeaSentence {
+ GpsUtcTime timestamp;
+ char nmea[NMEA_SENTENCE_LENGTH];
+};
+static NmeaSentence sNmeaBuffer[NMEA_SENTENCE_LENGTH];
+static int mNmeaSentenceCount = 0;
+
// a copy of the data shared by android_location_GpsLocationProvider_wait_for_event
// and android_location_GpsLocationProvider_read_status
static GpsLocation sGpsLocationCopy;
static GpsStatus sGpsStatusCopy;
static GpsSvStatus sGpsSvStatusCopy;
static AGpsStatus sAGpsStatusCopy;
+static NmeaSentence sNmeaBufferCopy[NMEA_SENTENCE_LENGTH];
enum CallbackType {
kLocation = 1,
@@ -58,6 +70,7 @@ enum CallbackType {
kAGpsStatus = 8,
kXtraDownloadRequest = 16,
kDisableRequest = 32,
+ kNmeaAvailable = 64,
};
static int sPendingCallbacks;
@@ -96,6 +109,30 @@ static void sv_status_callback(GpsSvStatus* sv_status)
pthread_mutex_unlock(&sEventMutex);
}
+static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
+{
+ pthread_mutex_lock(&sEventMutex);
+
+ if (length >= NMEA_SENTENCE_LENGTH) {
+ LOGE("NMEA data too long in nmea_callback (length = %d)\n", length);
+ length = NMEA_SENTENCE_LENGTH - 1;
+ }
+ if (mNmeaSentenceCount >= NMEA_SENTENCE_COUNT) {
+ LOGE("NMEA data overflowed buffer\n");
+ pthread_mutex_unlock(&sEventMutex);
+ return;
+ }
+
+ sPendingCallbacks |= kNmeaAvailable;
+ sNmeaBuffer[mNmeaSentenceCount].timestamp = timestamp;
+ memcpy(sNmeaBuffer[mNmeaSentenceCount].nmea, nmea, length);
+ sNmeaBuffer[mNmeaSentenceCount].nmea[length] = 0;
+ mNmeaSentenceCount++;
+
+ pthread_cond_signal(&sEventCond);
+ pthread_mutex_unlock(&sEventMutex);
+}
+
static void agps_status_callback(AGpsStatus* agps_status)
{
pthread_mutex_lock(&sEventMutex);
@@ -111,6 +148,7 @@ GpsCallbacks sGpsCallbacks = {
location_callback,
status_callback,
sv_status_callback,
+ nmea_callback
};
static void
@@ -135,6 +173,7 @@ static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env,
method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II)V");
+ method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(IJ)V");
method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
}
@@ -200,13 +239,21 @@ static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, job
// copy and clear the callback flags
int pendingCallbacks = sPendingCallbacks;
sPendingCallbacks = 0;
+ int nmeaSentenceCount = mNmeaSentenceCount;
+ mNmeaSentenceCount = 0;
// copy everything and unlock the mutex before calling into Java code to avoid the possibility
// of timeouts in the GPS engine.
- memcpy(&sGpsLocationCopy, &sGpsLocation, sizeof(sGpsLocationCopy));
- memcpy(&sGpsStatusCopy, &sGpsStatus, sizeof(sGpsStatusCopy));
- memcpy(&sGpsSvStatusCopy, &sGpsSvStatus, sizeof(sGpsSvStatusCopy));
- memcpy(&sAGpsStatusCopy, &sAGpsStatus, sizeof(sAGpsStatusCopy));
+ if (pendingCallbacks & kLocation)
+ memcpy(&sGpsLocationCopy, &sGpsLocation, sizeof(sGpsLocationCopy));
+ if (pendingCallbacks & kStatus)
+ memcpy(&sGpsStatusCopy, &sGpsStatus, sizeof(sGpsStatusCopy));
+ if (pendingCallbacks & kSvStatus)
+ memcpy(&sGpsSvStatusCopy, &sGpsSvStatus, sizeof(sGpsSvStatusCopy));
+ if (pendingCallbacks & kAGpsStatus)
+ memcpy(&sAGpsStatusCopy, &sAGpsStatus, sizeof(sAGpsStatusCopy));
+ if (pendingCallbacks & kNmeaAvailable)
+ memcpy(&sNmeaBufferCopy, &sNmeaBuffer, nmeaSentenceCount * sizeof(sNmeaBuffer[0]));
pthread_mutex_unlock(&sEventMutex);
if (pendingCallbacks & kLocation) {
@@ -225,6 +272,11 @@ static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, job
if (pendingCallbacks & kAGpsStatus) {
env->CallVoidMethod(obj, method_reportAGpsStatus, sAGpsStatusCopy.type, sAGpsStatusCopy.status);
}
+ if (pendingCallbacks & kNmeaAvailable) {
+ for (int i = 0; i < nmeaSentenceCount; i++) {
+ env->CallVoidMethod(obj, method_reportNmea, i, sNmeaBuffer[i].timestamp);
+ }
+ }
if (pendingCallbacks & kXtraDownloadRequest) {
env->CallVoidMethod(obj, method_xtraDownloadRequest);
}
@@ -264,6 +316,21 @@ static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, job
return num_svs;
}
+static jint android_location_GpsLocationProvider_read_nmea(JNIEnv* env, jobject obj, jint index, jbyteArray nmeaArray, jint buffer_size)
+{
+ // this should only be called from within a call to reportStatus, so we don't need to lock here
+
+ jbyte* nmea = env->GetByteArrayElements(nmeaArray, 0);
+
+ int length = strlen(sNmeaBuffer[index].nmea);
+ if (length > buffer_size)
+ length = buffer_size;
+ memcpy(nmea, sNmeaBuffer[index].nmea, length);
+
+ env->ReleaseByteArrayElements(nmeaArray, nmea, 0);
+ return length;
+}
+
static void android_location_GpsLocationProvider_inject_time(JNIEnv* env, jobject obj, jlong time,
jlong timeReference, jint uncertainty)
{
@@ -360,6 +427,7 @@ static JNINativeMethod sMethods[] = {
{"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data},
{"native_wait_for_event", "()V", (void*)android_location_GpsLocationProvider_wait_for_event},
{"native_read_sv_status", "([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status},
+ {"native_read_nmea", "(I[BI)I", (void*)android_location_GpsLocationProvider_read_nmea},
{"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time},
{"native_inject_location", "(DDF)V", (void*)android_location_GpsLocationProvider_inject_location},
{"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra},