diff options
Diffstat (limited to 'location/java/android')
-rw-r--r-- | location/java/android/location/GpsStatus.java | 9 | ||||
-rw-r--r-- | location/java/android/location/IGpsStatusListener.aidl | 1 | ||||
-rw-r--r-- | location/java/android/location/LocationManager.java | 146 |
3 files changed, 136 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} |