summaryrefslogtreecommitdiffstats
path: root/location
diff options
context:
space:
mode:
authordestradaa <destradaa@google.com>2014-07-21 18:01:47 -0700
committerdestradaa <destradaa@google.com>2014-07-23 10:30:21 -0700
commit4b3e3931270f8e406fc806bc7fa1c2788256687d (patch)
treeb2b057ff2396faa88e2d21743199f6bd52ce2a74 /location
parent5320b04fe74f0120f84dd9fe09785491f42a766b (diff)
downloadframeworks_base-4b3e3931270f8e406fc806bc7fa1c2788256687d.zip
frameworks_base-4b3e3931270f8e406fc806bc7fa1c2788256687d.tar.gz
frameworks_base-4b3e3931270f8e406fc806bc7fa1c2788256687d.tar.bz2
Expose Gps Navigation Messages in the platform.
b/16405976 Change-Id: Ic982ea2467d116585780c20c2fa7e974e50f8345
Diffstat (limited to 'location')
-rw-r--r--location/java/android/location/GpsMeasurementListenerTransport.java90
-rw-r--r--location/java/android/location/GpsNavigationMessage.java276
-rw-r--r--location/java/android/location/GpsNavigationMessageEvent.aidl19
-rw-r--r--location/java/android/location/GpsNavigationMessageEvent.java92
-rw-r--r--location/java/android/location/GpsNavigationMessageListenerTransport.java69
-rw-r--r--location/java/android/location/IGpsNavigationMessageListener.aidl26
-rw-r--r--location/java/android/location/ILocationManager.aidl6
-rw-r--r--location/java/android/location/LocalListenerHelper.java109
-rw-r--r--location/java/android/location/LocationManager.java29
9 files changed, 646 insertions, 70 deletions
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<GpsMeasurementsEvent.Listener> {
private final Context mContext;
private final ILocationManager mLocationManager;
private final IGpsMeasurementsListener mListenerTransport = new ListenerTransport();
- private final HashSet<GpsMeasurementsEvent.Listener> mListeners =
- new HashSet<GpsMeasurementsEvent.Listener>();
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<GpsMeasurementsEvent.Listener> listeners;
- synchronized (mListeners) {
- listeners = new ArrayList<GpsMeasurementsEvent.Listener>(mListeners);
- }
+ public void onGpsMeasurementsReceived(final GpsMeasurementsEvent event) {
+ ListenerOperation<GpsMeasurementsEvent.Listener> operation =
+ new ListenerOperation<GpsMeasurementsEvent.Listener>() {
+ @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 "<Invalid>";
+ }
+ }
+
+ /**
+ * 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<GpsNavigationMessage> CREATOR =
+ new Creator<GpsNavigationMessage>() {
+ @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<GpsNavigationMessageEvent> CREATOR =
+ new Creator<GpsNavigationMessageEvent>() {
+ @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<GpsNavigationMessageEvent.Listener> {
+ 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<GpsNavigationMessageEvent.Listener> operation =
+ new ListenerOperation<GpsNavigationMessageEvent.Listener>() {
+ @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<String> getAllProviders();
List<String> 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<TListener> {
+ private final HashSet<TListener> mListeners = new HashSet<TListener>();
+ 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<TListener> {
+ void execute(TListener listener) throws RemoteException;
+ }
+
+ protected void foreach(ListenerOperation operation) {
+ Collection<TListener> listeners;
+ synchronized (mListeners) {
+ listeners = new ArrayList<TListener>(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<GpsStatus.Listener, GpsStatusListenerTransport> mGpsStatusListeners =
new HashMap<GpsStatus.Listener, GpsStatusListenerTransport>();
private final HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport> 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}