From 4b3e3931270f8e406fc806bc7fa1c2788256687d Mon Sep 17 00:00:00 2001 From: destradaa Date: Mon, 21 Jul 2014 18:01:47 -0700 Subject: Expose Gps Navigation Messages in the platform. b/16405976 Change-Id: Ic982ea2467d116585780c20c2fa7e974e50f8345 --- .../location/GpsMeasurementListenerTransport.java | 90 ++----- .../android/location/GpsNavigationMessage.java | 276 +++++++++++++++++++++ .../location/GpsNavigationMessageEvent.aidl | 19 ++ .../location/GpsNavigationMessageEvent.java | 92 +++++++ .../GpsNavigationMessageListenerTransport.java | 69 ++++++ .../location/IGpsNavigationMessageListener.aidl | 26 ++ .../java/android/location/ILocationManager.aidl | 6 + .../java/android/location/LocalListenerHelper.java | 109 ++++++++ .../java/android/location/LocationManager.java | 29 ++- 9 files changed, 646 insertions(+), 70 deletions(-) create mode 100644 location/java/android/location/GpsNavigationMessage.java create mode 100644 location/java/android/location/GpsNavigationMessageEvent.aidl create mode 100644 location/java/android/location/GpsNavigationMessageEvent.java create mode 100644 location/java/android/location/GpsNavigationMessageListenerTransport.java create mode 100644 location/java/android/location/IGpsNavigationMessageListener.aidl create mode 100644 location/java/android/location/LocalListenerHelper.java (limited to 'location') diff --git a/location/java/android/location/GpsMeasurementListenerTransport.java b/location/java/android/location/GpsMeasurementListenerTransport.java index 48a4b44..2d9a372 100644 --- a/location/java/android/location/GpsMeasurementListenerTransport.java +++ b/location/java/android/location/GpsMeasurementListenerTransport.java @@ -16,99 +16,51 @@ package android.location; -import com.android.internal.util.Preconditions; - -import android.annotation.NonNull; import android.content.Context; import android.os.RemoteException; -import android.util.Log; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; /** - * A handler class to manage transport listeners for {@link GpsMeasurementsEvent.Listener}, - * and post the events in a handler. + * A handler class to manage transport listeners for {@link GpsMeasurementsEvent.Listener}. * * @hide */ -class GpsMeasurementListenerTransport { - private static final String TAG = "GpsMeasurementListenerTransport"; - +class GpsMeasurementListenerTransport + extends LocalListenerHelper { private final Context mContext; private final ILocationManager mLocationManager; private final IGpsMeasurementsListener mListenerTransport = new ListenerTransport(); - private final HashSet mListeners = - new HashSet(); public GpsMeasurementListenerTransport(Context context, ILocationManager locationManager) { + super("GpsMeasurementListenerTransport"); mContext = context; mLocationManager = locationManager; } - public boolean add(@NonNull GpsMeasurementsEvent.Listener listener) { - Preconditions.checkNotNull(listener); - - synchronized (mListeners) { - // we need to register with the service first, because we need to find out if the - // service will actually support the request before we attempt anything - if (mListeners.isEmpty()) { - boolean registeredWithServer; - try { - registeredWithServer = mLocationManager.addGpsMeasurementsListener( - mListenerTransport, - mContext.getPackageName()); - } catch (RemoteException e) { - Log.e(TAG, "Error handling first listener.", e); - return false; - } - - if (!registeredWithServer) { - Log.e(TAG, "Unable to register listener transport."); - return false; - } - } - - if (mListeners.contains(listener)) { - return true; - } - - mListeners.add(listener); - } - - return true; + @Override + protected boolean registerWithServer() throws RemoteException { + return mLocationManager.addGpsMeasurementsListener( + mListenerTransport, + mContext.getPackageName()); } - public void remove(@NonNull GpsMeasurementsEvent.Listener listener) { - Preconditions.checkNotNull(listener); - - synchronized (mListeners) { - boolean removed = mListeners.remove(listener); - - boolean isLastListener = removed && mListeners.isEmpty(); - if (isLastListener) { - try { - mLocationManager.removeGpsMeasurementsListener(mListenerTransport); - } catch (RemoteException e) { - Log.e(TAG, "Error handling last listener.", e); - } - } - } + @Override + protected void unregisterFromServer() throws RemoteException { + mLocationManager.removeGpsMeasurementsListener(mListenerTransport); } private class ListenerTransport extends IGpsMeasurementsListener.Stub { @Override - public void onGpsMeasurementsReceived(final GpsMeasurementsEvent eventArgs) { - Collection listeners; - synchronized (mListeners) { - listeners = new ArrayList(mListeners); - } + public void onGpsMeasurementsReceived(final GpsMeasurementsEvent event) { + ListenerOperation operation = + new ListenerOperation() { + @Override + public void execute(GpsMeasurementsEvent.Listener listener) throws RemoteException { + listener.onGpsMeasurementsReceived(event); + } + }; - for (final GpsMeasurementsEvent.Listener listener : listeners) { - listener.onGpsMeasurementsReceived(eventArgs); - } + foreach(operation); } } } diff --git a/location/java/android/location/GpsNavigationMessage.java b/location/java/android/location/GpsNavigationMessage.java new file mode 100644 index 0000000..2eb4708 --- /dev/null +++ b/location/java/android/location/GpsNavigationMessage.java @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.location; + +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +import java.security.InvalidParameterException; + +/** + * A class containing a GPS satellite Navigation Message. + * + * @hide + */ +public class GpsNavigationMessage implements Parcelable { + private static final String TAG = "GpsNavigationMessage"; + private static final byte[] EMPTY_ARRAY = new byte[0]; + + // The following enumerations must be in sync with the values declared in gps.h + + /** + * The type of the navigation message is not available or unknown. + */ + public static final byte TYPE_UNKNOWN = 0; + + /** + * The Navigation Message is of type L1 C/A. + */ + public static final byte TYPE_L1CA = 1; + + /** + * The Navigation Message is of type L1-CNAV. + */ + public static final byte TYPE_L2CNAV = 2; + + /** + * The Navigation Message is of type L5-CNAV. + */ + public static final byte TYPE_L5CNAV = 3; + + /** + * The Navigation Message is of type CNAV-2. + */ + public static final byte TYPE_CNAV2 = 4; + + // End enumerations in sync with gps.h + + private byte mType; + private byte mPrn; + private short mMessageId; + private short mSubmessageId; + private byte[] mData; + + GpsNavigationMessage() { + initialize(); + } + + /** + * Sets all contents to the values stored in the provided object. + */ + public void set(GpsNavigationMessage navigationMessage) { + mType = navigationMessage.mType; + mPrn = navigationMessage.mPrn; + mMessageId = navigationMessage.mMessageId; + mSubmessageId = navigationMessage.mSubmessageId; + mData = navigationMessage.mData; + } + + /** + * Resets all the contents to its original state. + */ + public void reset() { + initialize(); + } + + /** + * Gets the type of the navigation message contained in the object. + */ + public byte getType() { + return mType; + } + + /** + * Sets the type of the navigation message. + */ + public void setType(byte value) { + switch (value) { + case TYPE_UNKNOWN: + case TYPE_L1CA: + case TYPE_L2CNAV: + case TYPE_L5CNAV: + case TYPE_CNAV2: + mType = value; + break; + default: + Log.d(TAG, "Sanitizing invalid 'type': " + value); + mType = TYPE_UNKNOWN; + break; + } + } + + /** + * Gets a string representation of the 'type'. + * For internal and logging use only. + */ + private String getTypeString() { + switch (mType) { + case TYPE_UNKNOWN: + return "Unknown"; + case TYPE_L1CA: + return "L1 C/A"; + case TYPE_L2CNAV: + return "L2-CNAV"; + case TYPE_L5CNAV: + return "L5-CNAV"; + case TYPE_CNAV2: + return "CNAV-2"; + default: + return ""; + } + } + + /** + * Gets the Pseudo-random number. + * Range: [1, 32]. + */ + public byte getPrn() { + return mPrn; + } + + /** + * Sets the Pseud-random number. + */ + public void setPrn(byte value) { + mPrn = value; + } + + /** + * Gets the Message Identifier. + * It provides an index so the complete Navigation Message can be assembled. i.e. for L1 C/A + * subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message. + * Subframe 1, 2, 3 does not contain a 'frame id' and this might be reported as -1. + */ + public short getMessageId() { + return mMessageId; + } + + /** + * Sets the Message Identifier. + */ + public void setMessageId(short value) { + mMessageId = value; + } + + /** + * Gets the Sub-message Identifier. + * If required by {@link #getType()}, this value contains a sub-index within the current message + * (or frame) that is being transmitted. i.e. for L1 C/A the sub-message identifier corresponds + * to the sub-frame Id of the navigation message. + */ + public short getSubmessageId() { + return mSubmessageId; + } + + /** + * Sets the Sub-message identifier. + */ + public void setSubmessageId(short value) { + mSubmessageId = value; + } + + /** + * Gets the data associated with the Navigation Message. + * The bytes (or words) specified using big endian format (MSB first). + */ + @NonNull + public byte[] getData() { + return mData; + } + + /** + * Sets the data associated with the Navigation Message. + */ + public void setData(byte[] value) { + if (value == null) { + throw new InvalidParameterException("Data must be a non-null array"); + } + + mData = value; + } + + public static final Creator CREATOR = + new Creator() { + @Override + public GpsNavigationMessage createFromParcel(Parcel parcel) { + GpsNavigationMessage navigationMessage = new GpsNavigationMessage(); + + navigationMessage.setType(parcel.readByte()); + navigationMessage.setPrn(parcel.readByte()); + navigationMessage.setMessageId((short) parcel.readInt()); + navigationMessage.setSubmessageId((short) parcel.readInt()); + + int dataLength = parcel.readInt(); + byte[] data = new byte[dataLength]; + parcel.readByteArray(data); + navigationMessage.setData(data); + + return navigationMessage; + } + + @Override + public GpsNavigationMessage[] newArray(int size) { + return new GpsNavigationMessage[size]; + } + }; + + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeByte(mType); + parcel.writeByte(mPrn); + parcel.writeInt(mMessageId); + parcel.writeInt(mSubmessageId); + parcel.writeInt(mData.length); + parcel.writeByteArray(mData); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public String toString() { + final String format = " %-15s = %s\n"; + StringBuilder builder = new StringBuilder("GpsNavigationMessage:\n"); + + builder.append(String.format(format, "Type", getTypeString())); + builder.append(String.format(format, "Prn", mPrn)); + builder.append(String.format(format, "MessageId", mMessageId)); + builder.append(String.format(format, "SubmessageId", mSubmessageId)); + + builder.append(String.format(format, "Data", "{")); + String prefix = " "; + for(byte value : mData) { + builder.append(prefix); + builder.append(value); + prefix = ", "; + } + builder.append(" }"); + + return builder.toString(); + } + + private void initialize() { + mType = TYPE_UNKNOWN; + mPrn = 0; + mMessageId = -1; + mSubmessageId = -1; + mData = EMPTY_ARRAY; + } +} diff --git a/location/java/android/location/GpsNavigationMessageEvent.aidl b/location/java/android/location/GpsNavigationMessageEvent.aidl new file mode 100644 index 0000000..f84c2f7 --- /dev/null +++ b/location/java/android/location/GpsNavigationMessageEvent.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2014, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.location; + +parcelable GpsNavigationMessageEvent; diff --git a/location/java/android/location/GpsNavigationMessageEvent.java b/location/java/android/location/GpsNavigationMessageEvent.java new file mode 100644 index 0000000..50ffa75 --- /dev/null +++ b/location/java/android/location/GpsNavigationMessageEvent.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.location; + +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import java.security.InvalidParameterException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +/** + * A class implementing a container for data associated with a navigation message event. + * Events are delivered to registered instances of {@link Listener}. + * + * @hide + */ +public class GpsNavigationMessageEvent implements Parcelable { + private final GpsNavigationMessage mNavigationMessage; + + /** + * Used for receiving GPS satellite Navigation Messages from the GPS engine. + * You can implement this interface and call + * {@link LocationManager#addGpsNavigationMessageListener}. + * + * @hide + */ + public interface Listener { + void onGpsNavigationMessageReceived(GpsNavigationMessageEvent event); + } + + public GpsNavigationMessageEvent(GpsNavigationMessage message) { + if (message == null) { + throw new InvalidParameterException("Parameter 'message' must not be null."); + } + mNavigationMessage = message; + } + + @NonNull + public GpsNavigationMessage getNavigationMessage() { + return mNavigationMessage; + } + + public static final Creator CREATOR = + new Creator() { + @Override + public GpsNavigationMessageEvent createFromParcel(Parcel in) { + ClassLoader classLoader = getClass().getClassLoader(); + GpsNavigationMessage navigationMessage = in.readParcelable(classLoader); + return new GpsNavigationMessageEvent(navigationMessage); + } + + @Override + public GpsNavigationMessageEvent[] newArray(int size) { + return new GpsNavigationMessageEvent[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeParcelable(mNavigationMessage, flags); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("[ GpsNavigationMessageEvent:\n\n"); + builder.append(mNavigationMessage.toString()); + builder.append("\n]"); + return builder.toString(); + } +} diff --git a/location/java/android/location/GpsNavigationMessageListenerTransport.java b/location/java/android/location/GpsNavigationMessageListenerTransport.java new file mode 100644 index 0000000..ec4812b --- /dev/null +++ b/location/java/android/location/GpsNavigationMessageListenerTransport.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.location; + +import android.content.Context; +import android.os.RemoteException; + +/** + * A handler class to manage transport listeners for {@link GpsNavigationMessageEvent.Listener}. + * + * @hide + */ +class GpsNavigationMessageListenerTransport + extends LocalListenerHelper { + private final Context mContext; + private final ILocationManager mLocationManager; + + private final IGpsNavigationMessageListener mListenerTransport = new ListenerTransport(); + + public GpsNavigationMessageListenerTransport( + Context context, + ILocationManager locationManager) { + super("GpsNavigationMessageListenerTransport"); + mContext = context; + mLocationManager = locationManager; + } + + @Override + protected boolean registerWithServer() throws RemoteException { + return mLocationManager.addGpsNavigationMessageListener( + mListenerTransport, + mContext.getPackageName()); + } + + @Override + protected void unregisterFromServer() throws RemoteException { + mLocationManager.removeGpsNavigationMessageListener(mListenerTransport); + } + + private class ListenerTransport extends IGpsNavigationMessageListener.Stub { + @Override + public void onGpsNavigationMessageReceived(final GpsNavigationMessageEvent event) { + ListenerOperation operation = + new ListenerOperation() { + @Override + public void execute(GpsNavigationMessageEvent.Listener listener) + throws RemoteException { + listener.onGpsNavigationMessageReceived(event); + } + }; + + foreach(operation); + } + } +} diff --git a/location/java/android/location/IGpsNavigationMessageListener.aidl b/location/java/android/location/IGpsNavigationMessageListener.aidl new file mode 100644 index 0000000..18603fe --- /dev/null +++ b/location/java/android/location/IGpsNavigationMessageListener.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2014, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.location; + +import android.location.GpsNavigationMessageEvent; + +/** + * {@hide} + */ +oneway interface IGpsNavigationMessageListener { + void onGpsNavigationMessageReceived(in GpsNavigationMessageEvent event); +} diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index a1acaf1..1501710 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -22,6 +22,7 @@ import android.location.Criteria; import android.location.GeocoderParams; import android.location.Geofence; import android.location.IGpsMeasurementsListener; +import android.location.IGpsNavigationMessageListener; import android.location.IGpsStatusListener; import android.location.ILocationListener; import android.location.Location; @@ -63,6 +64,11 @@ interface ILocationManager boolean addGpsMeasurementsListener(in IGpsMeasurementsListener listener, in String packageName); boolean removeGpsMeasurementsListener(in IGpsMeasurementsListener listener); + boolean addGpsNavigationMessageListener( + in IGpsNavigationMessageListener listener, + in String packageName); + boolean removeGpsNavigationMessageListener(in IGpsNavigationMessageListener listener); + // --- deprecated --- List getAllProviders(); List getProviders(in Criteria criteria, boolean enabledOnly); diff --git a/location/java/android/location/LocalListenerHelper.java b/location/java/android/location/LocalListenerHelper.java new file mode 100644 index 0000000..1f3bf67 --- /dev/null +++ b/location/java/android/location/LocalListenerHelper.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.location; + +import com.android.internal.util.Preconditions; + +import android.annotation.NonNull; +import android.os.RemoteException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; + +/** + * A base handler class to manage transport and local listeners. + * + * @hide + */ +abstract class LocalListenerHelper { + private final HashSet mListeners = new HashSet(); + private final String mTag; + + protected LocalListenerHelper(String name) { + Preconditions.checkNotNull(name); + mTag = name; + } + + public boolean add(@NonNull TListener listener) { + Preconditions.checkNotNull(listener); + + synchronized (mListeners) { + // we need to register with the service first, because we need to find out if the + // service will actually support the request before we attempt anything + if (mListeners.isEmpty()) { + boolean registeredWithService; + try { + registeredWithService = registerWithServer(); + } catch (RemoteException e) { + Log.e(mTag, "Error handling first listener.", e); + return false; + } + if (!registeredWithService) { + Log.e(mTag, "Unable to register listener transport."); + return false; + } + } + + if (mListeners.contains(listener)) { + return true; + } + mListeners.add(listener); + } + return true; + } + + public void remove(@NonNull TListener listener) { + Preconditions.checkNotNull(listener); + + synchronized (mListeners) { + boolean removed = mListeners.remove(listener); + boolean isLastRemoved = removed && mListeners.isEmpty(); + if (isLastRemoved) { + try { + unregisterFromServer(); + } catch (RemoteException e) { + + } + } + } + } + + protected abstract boolean registerWithServer() throws RemoteException; + protected abstract void unregisterFromServer() throws RemoteException; + + protected interface ListenerOperation { + void execute(TListener listener) throws RemoteException; + } + + protected void foreach(ListenerOperation operation) { + Collection listeners; + synchronized (mListeners) { + listeners = new ArrayList(mListeners); + } + + for (TListener listener : listeners) { + try { + operation.execute(listener); + } catch (RemoteException e) { + Log.e(mTag, "Error in monitored listener.", e); + // don't return, give a fair chance to all listeners to receive the event + } + } + } +} diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index d6a8fb8..082a158 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -59,6 +59,7 @@ public class LocationManager { private final Context mContext; private final ILocationManager mService; private final GpsMeasurementListenerTransport mGpsMeasurementListenerTransport; + private final GpsNavigationMessageListenerTransport mGpsNavigationMessageListenerTransport; private final HashMap mGpsStatusListeners = new HashMap(); private final HashMap mNmeaListeners = @@ -310,6 +311,8 @@ public class LocationManager { mService = service; mContext = context; mGpsMeasurementListenerTransport = new GpsMeasurementListenerTransport(mContext, mService); + mGpsNavigationMessageListenerTransport = + new GpsNavigationMessageListenerTransport(mContext, mService); } private LocationProvider createProvider(String name, ProviderProperties properties) { @@ -1573,7 +1576,7 @@ public class LocationManager { /** * Adds a GPS Measurement listener. * - * @param listener a {@link android.location.GpsMeasurementsEvent.Listener} object to register. + * @param listener a {@link GpsMeasurementsEvent.Listener} object to register. * @return {@code true} if the listener was successfully registered, {@code false} otherwise. * * @hide @@ -1593,6 +1596,30 @@ public class LocationManager { mGpsMeasurementListenerTransport.remove(listener); } + /** + * Adds a GPS Navigation Message listener. + * + * @param listener a {@link GpsNavigationMessageEvent.Listener} object to register. + * @return {@code true} if the listener was successfully registered, {@code false} otherwise. + * + * @hide + */ + public boolean addGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) { + return mGpsNavigationMessageListenerTransport.add(listener); + } + + /** + * Removes a GPS Navigation Message listener. + * + * @param listener a {@link GpsNavigationMessageEvent.Listener} object to remove. + * + * @hide + */ + public void removeGpsNavigationMessageListener( + GpsNavigationMessageEvent.Listener listener) { + mGpsNavigationMessageListenerTransport.remove(listener); + } + /** * Retrieves information about the current status of the GPS engine. * This should only be called from the {@link GpsStatus.Listener#onGpsStatusChanged} -- cgit v1.1