summaryrefslogtreecommitdiffstats
path: root/location/java
diff options
context:
space:
mode:
Diffstat (limited to 'location/java')
-rw-r--r--location/java/android/location/GpsStatus.java9
-rw-r--r--location/java/android/location/IGpsStatusListener.aidl1
-rw-r--r--location/java/android/location/LocationManager.java146
-rwxr-xr-xlocation/java/com/android/internal/location/GpsLocationProvider.java29
4 files changed, 165 insertions, 20 deletions
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index 2cda7fa..883ee4f 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -115,6 +115,15 @@ public final class GpsStatus {
void onGpsStatusChanged(int event);
}
+ /**
+ * Used for receiving NMEA data from the GPS.
+ *
+ * {@hide}
+ */
+ public interface NmeaListener {
+ void onNmeaReceived(long timestamp, String nmea);
+ }
+
GpsStatus() {
for (int i = 0; i < mSatellites.length; i++) {
mSatellites[i] = new GpsSatellite(i + 1);
diff --git a/location/java/android/location/IGpsStatusListener.aidl b/location/java/android/location/IGpsStatusListener.aidl
index 5dc0fe8..62b1c6b 100644
--- a/location/java/android/location/IGpsStatusListener.aidl
+++ b/location/java/android/location/IGpsStatusListener.aidl
@@ -29,4 +29,5 @@ oneway interface IGpsStatusListener
void onSvStatusChanged(int svCount, in int[] prns, in float[] snrs,
in float[] elevations, in float[] azimuths,
int ephemerisMask, int almanacMask, int usedInFixMask);
+ void onNmeaReceived(long timestamp, String nmea);
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index ca16f19..8f17e78 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -51,6 +51,8 @@ public class LocationManager {
private ILocationManager mService;
private final HashMap<GpsStatus.Listener, GpsStatusListenerTransport> mGpsStatusListeners =
new HashMap<GpsStatus.Listener, GpsStatusListenerTransport>();
+ private final HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport> mNmeaListeners =
+ new HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport>();
private final GpsStatus mGpsStatus = new GpsStatus();
/**
@@ -1123,49 +1125,103 @@ public class LocationManager {
private class GpsStatusListenerTransport extends IGpsStatusListener.Stub {
private final GpsStatus.Listener mListener;
+ private final GpsStatus.NmeaListener mNmeaListener;
+
+ // This must not equal any of the GpsStatus event IDs
+ private static final int NMEA_RECEIVED = 1000;
+
+ private class Nmea {
+ long mTimestamp;
+ String mNmea;
+
+ Nmea(long timestamp, String nmea) {
+ mTimestamp = timestamp;
+ mNmea = nmea;
+ }
+ }
+ private ArrayList<Nmea> mNmeaBuffer;
GpsStatusListenerTransport(GpsStatus.Listener listener) {
mListener = listener;
+ mNmeaListener = null;
+ }
+
+ GpsStatusListenerTransport(GpsStatus.NmeaListener listener) {
+ mNmeaListener = listener;
+ mListener = null;
+ mNmeaBuffer = new ArrayList<Nmea>();
}
public void onGpsStarted() {
- Message msg = Message.obtain();
- msg.what = GpsStatus.GPS_EVENT_STARTED;
- mGpsHandler.sendMessage(msg);
+ if (mListener != null) {
+ Message msg = Message.obtain();
+ msg.what = GpsStatus.GPS_EVENT_STARTED;
+ mGpsHandler.sendMessage(msg);
+ }
}
public void onGpsStopped() {
- Message msg = Message.obtain();
- msg.what = GpsStatus.GPS_EVENT_STOPPED;
- mGpsHandler.sendMessage(msg);
+ if (mListener != null) {
+ Message msg = Message.obtain();
+ msg.what = GpsStatus.GPS_EVENT_STOPPED;
+ mGpsHandler.sendMessage(msg);
+ }
}
public void onFirstFix(int ttff) {
- mGpsStatus.setTimeToFirstFix(ttff);
- Message msg = Message.obtain();
- msg.what = GpsStatus.GPS_EVENT_FIRST_FIX;
- mGpsHandler.sendMessage(msg);
+ if (mListener != null) {
+ mGpsStatus.setTimeToFirstFix(ttff);
+ Message msg = Message.obtain();
+ msg.what = GpsStatus.GPS_EVENT_FIRST_FIX;
+ mGpsHandler.sendMessage(msg);
+ }
}
public void onSvStatusChanged(int svCount, int[] prns, float[] snrs,
float[] elevations, float[] azimuths, int ephemerisMask,
int almanacMask, int usedInFixMask) {
- mGpsStatus.setStatus(svCount, prns, snrs, elevations, azimuths,
- ephemerisMask, almanacMask, usedInFixMask);
+ if (mListener != null) {
+ mGpsStatus.setStatus(svCount, prns, snrs, elevations, azimuths,
+ ephemerisMask, almanacMask, usedInFixMask);
+
+ Message msg = Message.obtain();
+ msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS;
+ // remove any SV status messages already in the queue
+ mGpsHandler.removeMessages(GpsStatus.GPS_EVENT_SATELLITE_STATUS);
+ mGpsHandler.sendMessage(msg);
+ }
+ }
- Message msg = Message.obtain();
- msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS;
- // remove any SV status messages already in the queue
- mGpsHandler.removeMessages(GpsStatus.GPS_EVENT_SATELLITE_STATUS);
- mGpsHandler.sendMessage(msg);
+ public void onNmeaReceived(long timestamp, String nmea) {
+ if (mNmeaListener != null) {
+ synchronized (mNmeaBuffer) {
+ mNmeaBuffer.add(new Nmea(timestamp, nmea));
+ }
+ Message msg = Message.obtain();
+ msg.what = NMEA_RECEIVED;
+ // remove any NMEA_RECEIVED messages already in the queue
+ mGpsHandler.removeMessages(NMEA_RECEIVED);
+ mGpsHandler.sendMessage(msg);
+ }
}
private final Handler mGpsHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
- // synchronize on mGpsStatus to ensure the data is copied atomically.
- synchronized(mGpsStatus) {
- mListener.onGpsStatusChanged(msg.what);
+ if (msg.what == NMEA_RECEIVED) {
+ synchronized (mNmeaBuffer) {
+ int length = mNmeaBuffer.size();
+ for (int i = 0; i < length; i++) {
+ Nmea nmea = mNmeaBuffer.get(i);
+ mNmeaListener.onNmeaReceived(nmea.mTimestamp, nmea.mNmea);
+ }
+ mNmeaBuffer.clear();
+ }
+ } else {
+ // synchronize on mGpsStatus to ensure the data is copied atomically.
+ synchronized(mGpsStatus) {
+ mListener.onGpsStatusChanged(msg.what);
+ }
}
}
};
@@ -1217,6 +1273,56 @@ public class LocationManager {
}
}
+ /**
+ * Adds an NMEA listener.
+ *
+ * @param listener NMEA listener object to register
+ *
+ * @return true if the listener was successfully added
+ *
+ * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+ *
+ * {@hide}
+ */
+ public boolean addNmeaListener(GpsStatus.NmeaListener listener) {
+ boolean result;
+
+ if (mNmeaListeners.get(listener) != null) {
+ // listener is already registered
+ return true;
+ }
+ try {
+ GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener);
+ result = mService.addGpsStatusListener(transport);
+ if (result) {
+ mNmeaListeners.put(listener, transport);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in registerGpsStatusListener: ", e);
+ result = false;
+ }
+
+ return result;
+ }
+
+ /**
+ * Removes an NMEA listener.
+ *
+ * @param listener NMEA listener object to remove
+ *
+ * {@hide}
+ */
+ public void removeNmeaListener(GpsStatus.NmeaListener listener) {
+ try {
+ GpsStatusListenerTransport transport = mNmeaListeners.remove(listener);
+ if (transport != null) {
+ mService.removeGpsStatusListener(transport);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e);
+ }
+ }
+
/**
* Retrieves information about the current status of the GPS engine.
* This should only be called from the {@link GpsStatus.Listener#onGpsStatusChanged}
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index aaac192..bdef01f 100755
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -1014,6 +1014,32 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
}
}
+ /**
+ * called from native code to report NMEA data received
+ */
+ private void reportNmea(int index, long timestamp) {
+ synchronized(mListeners) {
+ int size = mListeners.size();
+ if (size > 0) {
+ // don't bother creating the String if we have no listeners
+ int length = native_read_nmea(index, mNmeaBuffer, mNmeaBuffer.length);
+ String nmea = new String(mNmeaBuffer, 0, length);
+
+ for (int i = 0; i < size; i++) {
+ Listener listener = mListeners.get(i);
+ try {
+ listener.mListener.onNmeaReceived(timestamp, nmea);
+ } catch (RemoteException e) {
+ Log.w(TAG, "RemoteException in reportNmea");
+ mListeners.remove(listener);
+ // adjust for size of list changing
+ size--;
+ }
+ }
+ }
+ }
+ }
+
private void xtraDownloadRequest() {
if (Config.LOGD) Log.d(TAG, "xtraDownloadRequest");
if (mNetworkThread != null) {
@@ -1194,6 +1220,8 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
private float mSvAzimuths[] = new float[MAX_SVS];
private int mSvMasks[] = new int[3];
private int mSvCount;
+ // preallocated to avoid memory allocation in reportNmea()
+ private byte[] mNmeaBuffer = new byte[120];
static { class_init_native(); }
private static native void class_init_native();
@@ -1211,6 +1239,7 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
// mask[0] is ephemeris mask and mask[1] is almanac mask
private native int native_read_sv_status(int[] svs, float[] snrs,
float[] elevations, float[] azimuths, int[] masks);
+ private native int native_read_nmea(int index, byte[] buffer, int bufferSize);
private native void native_inject_location(double latitude, double longitude, float accuracy);
// XTRA Support