From 30f95a7d67870c28d2aaa88ee989c099f5670225 Mon Sep 17 00:00:00 2001 From: Lifu Tang Date: Thu, 7 Jan 2016 23:20:38 -0800 Subject: [PATCH] Supported GNSS multi-constellation in frameworks Change-Id: I82574afd3697c47e806d2cfaedc33756d0353b73 --- Android.mk | 4 +- api/current.txt | 47 ++- api/system-current.txt | 47 ++- api/test-current.txt | 47 ++- .../java/android/net/ConnectivityManager.java | 4 +- .../internal/app/NetInitiatedActivity.java | 2 +- .../android/location/GnssNmeaListener.java | 30 ++ .../java/android/location/GnssStatus.java | 140 +++++++ .../android/location/GnssStatusCallback.java | 44 +++ location/java/android/location/GpsStatus.java | 81 ++-- ...Listener.aidl => IGnssStatusListener.aidl} | 11 +- ...Provider.aidl => IGnssStatusProvider.aidl} | 10 +- .../android/location/ILocationManager.aidl | 6 +- .../android/location/LocationManager.java | 362 ++++++++++++++---- .../location/GpsNetInitiatedHandler.java | 2 +- .../server/LocationManagerService.java | 40 +- ...rovider.java => GnssLocationProvider.java} | 82 ++-- ...per.java => GnssStatusListenerHelper.java} | 42 +- services/core/jni/Android.mk | 2 +- ..._server_location_GnssLocationProvider.cpp} | 239 +++++++----- services/core/jni/onload.cpp | 4 +- 21 files changed, 907 insertions(+), 339 deletions(-) create mode 100644 location/java/android/location/GnssNmeaListener.java create mode 100644 location/java/android/location/GnssStatus.java create mode 100644 location/java/android/location/GnssStatusCallback.java rename location/java/android/location/{IGpsStatusListener.aidl => IGnssStatusListener.aidl} (73%) rename location/java/android/location/{IGpsStatusProvider.aidl => IGnssStatusProvider.aidl} (69%) rename services/core/java/com/android/server/location/{GpsLocationProvider.java => GnssLocationProvider.java} (97%) rename services/core/java/com/android/server/location/{GpsStatusListenerHelper.java => GnssStatusListenerHelper.java} (62%) rename services/core/jni/{com_android_server_location_GpsLocationProvider.cpp => com_android_server_location_GnssLocationProvider.cpp} (85%) diff --git a/Android.mk b/Android.mk index 51dfa575b77f3..e5fd2c760b192 100644 --- a/Android.mk +++ b/Android.mk @@ -327,10 +327,10 @@ LOCAL_SRC_FILES += \ location/java/android/location/IFusedProvider.aidl \ location/java/android/location/IGeocodeProvider.aidl \ location/java/android/location/IGeofenceProvider.aidl \ + location/java/android/location/IGnssStatusListener.aidl \ + location/java/android/location/IGnssStatusProvider.aidl \ location/java/android/location/IGpsMeasurementsListener.aidl \ location/java/android/location/IGpsNavigationMessageListener.aidl \ - location/java/android/location/IGpsStatusListener.aidl \ - location/java/android/location/IGpsStatusProvider.aidl \ location/java/android/location/ILocationListener.aidl \ location/java/android/location/ILocationManager.aidl \ location/java/android/location/IFusedGeofenceHardware.aidl \ diff --git a/api/current.txt b/api/current.txt index e4962d822a4f0..6bddcfb47718b 100644 --- a/api/current.txt +++ b/api/current.txt @@ -18856,6 +18856,37 @@ package android.location { method public static boolean isPresent(); } + public abstract interface GnssNmeaListener { + method public abstract void onNmeaReceived(long, java.lang.String); + } + + public final class GnssStatus { + method public float getAzimuth(int); + method public int getConstellationType(int); + method public float getElevation(int); + method public int getNumSatellites(); + method public int getPrn(int); + method public float getSnr(int); + method public boolean hasAlmanac(int); + method public boolean hasEphemeris(int); + method public boolean usedInFix(int); + field public static final int CONSTELLATION_BEIDOU = 5; // 0x5 + field public static final int CONSTELLATION_GALILEO = 6; // 0x6 + field public static final int CONSTELLATION_GLONASS = 3; // 0x3 + field public static final int CONSTELLATION_GPS = 1; // 0x1 + field public static final int CONSTELLATION_QZSS = 4; // 0x4 + field public static final int CONSTELLATION_SBAS = 2; // 0x2 + field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0 + } + + public abstract class GnssStatusCallback { + ctor public GnssStatusCallback(); + method public void onFirstFix(int); + method public void onSatelliteStatusChanged(android.location.GnssStatus); + method public void onStarted(); + method public void onStopped(); + } + public final class GpsSatellite { method public float getAzimuth(); method public float getElevation(); @@ -18940,8 +18971,10 @@ package android.location { } public class LocationManager { - method public boolean addGpsStatusListener(android.location.GpsStatus.Listener); - method public boolean addNmeaListener(android.location.GpsStatus.NmeaListener); + method public deprecated boolean addGpsStatusListener(android.location.GpsStatus.Listener); + method public deprecated boolean addNmeaListener(android.location.GpsStatus.NmeaListener); + method public boolean addNmeaListener(android.location.GnssNmeaListener); + method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler); method public void addProximityAlert(double, double, float, long, android.app.PendingIntent); method public void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int); method public void clearTestProviderEnabled(java.lang.String); @@ -18949,14 +18982,17 @@ package android.location { method public void clearTestProviderStatus(java.lang.String); method public java.util.List getAllProviders(); method public java.lang.String getBestProvider(android.location.Criteria, boolean); - method public android.location.GpsStatus getGpsStatus(android.location.GpsStatus); + method public deprecated android.location.GpsStatus getGpsStatus(android.location.GpsStatus); method public android.location.Location getLastKnownLocation(java.lang.String); method public android.location.LocationProvider getProvider(java.lang.String); method public java.util.List getProviders(boolean); method public java.util.List getProviders(android.location.Criteria, boolean); method public boolean isProviderEnabled(java.lang.String); - method public void removeGpsStatusListener(android.location.GpsStatus.Listener); - method public void removeNmeaListener(android.location.GpsStatus.NmeaListener); + method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback); + method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler); + method public deprecated void removeGpsStatusListener(android.location.GpsStatus.Listener); + method public deprecated void removeNmeaListener(android.location.GpsStatus.NmeaListener); + method public void removeNmeaListener(android.location.GnssNmeaListener); method public void removeProximityAlert(android.app.PendingIntent); method public void removeTestProvider(java.lang.String); method public void removeUpdates(android.location.LocationListener); @@ -18974,6 +19010,7 @@ package android.location { method public void setTestProviderEnabled(java.lang.String, boolean); method public void setTestProviderLocation(java.lang.String, android.location.Location); method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long); + method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback); field public static final java.lang.String GPS_PROVIDER = "gps"; field public static final java.lang.String KEY_LOCATION_CHANGED = "location"; field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled"; diff --git a/api/system-current.txt b/api/system-current.txt index 586ea06df874b..8657544b8b028 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -19843,6 +19843,37 @@ package android.location { method public static boolean isPresent(); } + public abstract interface GnssNmeaListener { + method public abstract void onNmeaReceived(long, java.lang.String); + } + + public final class GnssStatus { + method public float getAzimuth(int); + method public int getConstellationType(int); + method public float getElevation(int); + method public int getNumSatellites(); + method public int getPrn(int); + method public float getSnr(int); + method public boolean hasAlmanac(int); + method public boolean hasEphemeris(int); + method public boolean usedInFix(int); + field public static final int CONSTELLATION_BEIDOU = 5; // 0x5 + field public static final int CONSTELLATION_GALILEO = 6; // 0x6 + field public static final int CONSTELLATION_GLONASS = 3; // 0x3 + field public static final int CONSTELLATION_GPS = 1; // 0x1 + field public static final int CONSTELLATION_QZSS = 4; // 0x4 + field public static final int CONSTELLATION_SBAS = 2; // 0x2 + field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0 + } + + public abstract class GnssStatusCallback { + ctor public GnssStatusCallback(); + method public void onFirstFix(int); + method public void onSatelliteStatusChanged(android.location.GnssStatus); + method public void onStarted(); + method public void onStopped(); + } + public class GpsClock implements android.os.Parcelable { method public int describeContents(); method public double getBiasInNs(); @@ -20174,8 +20205,10 @@ package android.location { public class LocationManager { method public boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener); method public boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener); - method public boolean addGpsStatusListener(android.location.GpsStatus.Listener); - method public boolean addNmeaListener(android.location.GpsStatus.NmeaListener); + method public deprecated boolean addGpsStatusListener(android.location.GpsStatus.Listener); + method public deprecated boolean addNmeaListener(android.location.GpsStatus.NmeaListener); + method public boolean addNmeaListener(android.location.GnssNmeaListener); + method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler); method public void addProximityAlert(double, double, float, long, android.app.PendingIntent); method public void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int); method public void clearTestProviderEnabled(java.lang.String); @@ -20183,16 +20216,19 @@ package android.location { method public void clearTestProviderStatus(java.lang.String); method public java.util.List getAllProviders(); method public java.lang.String getBestProvider(android.location.Criteria, boolean); - method public android.location.GpsStatus getGpsStatus(android.location.GpsStatus); + method public deprecated android.location.GpsStatus getGpsStatus(android.location.GpsStatus); method public android.location.Location getLastKnownLocation(java.lang.String); method public android.location.LocationProvider getProvider(java.lang.String); method public java.util.List getProviders(boolean); method public java.util.List getProviders(android.location.Criteria, boolean); method public boolean isProviderEnabled(java.lang.String); + method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback); + method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler); method public void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener); method public void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener); - method public void removeGpsStatusListener(android.location.GpsStatus.Listener); - method public void removeNmeaListener(android.location.GpsStatus.NmeaListener); + method public deprecated void removeGpsStatusListener(android.location.GpsStatus.Listener); + method public deprecated void removeNmeaListener(android.location.GpsStatus.NmeaListener); + method public void removeNmeaListener(android.location.GnssNmeaListener); method public void removeProximityAlert(android.app.PendingIntent); method public void removeTestProvider(java.lang.String); method public void removeUpdates(android.location.LocationListener); @@ -20212,6 +20248,7 @@ package android.location { method public void setTestProviderEnabled(java.lang.String, boolean); method public void setTestProviderLocation(java.lang.String, android.location.Location); method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long); + method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback); field public static final java.lang.String GPS_PROVIDER = "gps"; field public static final java.lang.String KEY_LOCATION_CHANGED = "location"; field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled"; diff --git a/api/test-current.txt b/api/test-current.txt index eccd8b006c827..cd1abaf74e94c 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -18856,6 +18856,37 @@ package android.location { method public static boolean isPresent(); } + public abstract interface GnssNmeaListener { + method public abstract void onNmeaReceived(long, java.lang.String); + } + + public final class GnssStatus { + method public float getAzimuth(int); + method public int getConstellationType(int); + method public float getElevation(int); + method public int getNumSatellites(); + method public int getPrn(int); + method public float getSnr(int); + method public boolean hasAlmanac(int); + method public boolean hasEphemeris(int); + method public boolean usedInFix(int); + field public static final int CONSTELLATION_BEIDOU = 5; // 0x5 + field public static final int CONSTELLATION_GALILEO = 6; // 0x6 + field public static final int CONSTELLATION_GLONASS = 3; // 0x3 + field public static final int CONSTELLATION_GPS = 1; // 0x1 + field public static final int CONSTELLATION_QZSS = 4; // 0x4 + field public static final int CONSTELLATION_SBAS = 2; // 0x2 + field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0 + } + + public abstract class GnssStatusCallback { + ctor public GnssStatusCallback(); + method public void onFirstFix(int); + method public void onSatelliteStatusChanged(android.location.GnssStatus); + method public void onStarted(); + method public void onStopped(); + } + public final class GpsSatellite { method public float getAzimuth(); method public float getElevation(); @@ -18940,8 +18971,10 @@ package android.location { } public class LocationManager { - method public boolean addGpsStatusListener(android.location.GpsStatus.Listener); - method public boolean addNmeaListener(android.location.GpsStatus.NmeaListener); + method public deprecated boolean addGpsStatusListener(android.location.GpsStatus.Listener); + method public deprecated boolean addNmeaListener(android.location.GpsStatus.NmeaListener); + method public boolean addNmeaListener(android.location.GnssNmeaListener); + method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler); method public void addProximityAlert(double, double, float, long, android.app.PendingIntent); method public void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int); method public void clearTestProviderEnabled(java.lang.String); @@ -18949,14 +18982,17 @@ package android.location { method public void clearTestProviderStatus(java.lang.String); method public java.util.List getAllProviders(); method public java.lang.String getBestProvider(android.location.Criteria, boolean); - method public android.location.GpsStatus getGpsStatus(android.location.GpsStatus); + method public deprecated android.location.GpsStatus getGpsStatus(android.location.GpsStatus); method public android.location.Location getLastKnownLocation(java.lang.String); method public android.location.LocationProvider getProvider(java.lang.String); method public java.util.List getProviders(boolean); method public java.util.List getProviders(android.location.Criteria, boolean); method public boolean isProviderEnabled(java.lang.String); - method public void removeGpsStatusListener(android.location.GpsStatus.Listener); - method public void removeNmeaListener(android.location.GpsStatus.NmeaListener); + method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback); + method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler); + method public deprecated void removeGpsStatusListener(android.location.GpsStatus.Listener); + method public deprecated void removeNmeaListener(android.location.GpsStatus.NmeaListener); + method public void removeNmeaListener(android.location.GnssNmeaListener); method public void removeProximityAlert(android.app.PendingIntent); method public void removeTestProvider(java.lang.String); method public void removeUpdates(android.location.LocationListener); @@ -18974,6 +19010,7 @@ package android.location { method public void setTestProviderEnabled(java.lang.String, boolean); method public void setTestProviderLocation(java.lang.String, android.location.Location); method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long); + method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback); field public static final java.lang.String GPS_PROVIDER = "gps"; field public static final java.lang.String KEY_LOCATION_CHANGED = "location"; field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled"; diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 515e9a27eefc9..03730a638c544 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -1058,7 +1058,7 @@ public class ConnectivityManager { return TYPE_NONE; } - // Do this only for SUPL, until GpsLocationProvider is fixed. http://b/25876485 . + // Do this only for SUPL, until GnssLocationProvider is fixed. http://b/25876485 . if (!netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) { // NOTE: if this causes app breakage, we should not just comment out this early return; // instead, we should make this early return conditional on the requesting app's target @@ -2938,7 +2938,7 @@ public class ConnectivityManager { // Checks whether the calling app can use the legacy routing API (startUsingNetworkFeature, // stopUsingNetworkFeature, requestRouteToHost), and if not throw UnsupportedOperationException. - // TODO: convert the existing system users (Tethering, GpsLocationProvider) to the new APIs and + // TODO: convert the existing system users (Tethering, GnssLocationProvider) to the new APIs and // remove these exemptions. Note that this check is not secure, and apps can still access these // functions by accessing ConnectivityService directly. However, it should be clear that doing // so is unsupported and may break in the future. http://b/22728205 diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java index b951f50e1cd0c..d3bae16d03a7b 100644 --- a/core/java/com/android/internal/app/NetInitiatedActivity.java +++ b/core/java/com/android/internal/app/NetInitiatedActivity.java @@ -133,7 +133,7 @@ public class NetInitiatedActivity extends AlertActivity implements DialogInterfa notificationId = -1; } - // Respond to NI Handler under GpsLocationProvider, 1 = accept, 2 = deny + // Respond to NI Handler under GnssLocationProvider, 1 = accept, 2 = deny private void sendUserResponse(int response) { if (DEBUG) Log.d(TAG, "sendUserResponse, response: " + response); LocationManager locationManager = (LocationManager) diff --git a/location/java/android/location/GnssNmeaListener.java b/location/java/android/location/GnssNmeaListener.java new file mode 100644 index 0000000000000..6c9b08a67bd12 --- /dev/null +++ b/location/java/android/location/GnssNmeaListener.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2016 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; + +/** +* Used for receiving NMEA sentences from the GNSS. +* NMEA 0183 is a standard for communicating with marine electronic devices +* and is a common method for receiving data from a GNSS, typically over a serial port. +* See NMEA 0183 for more details. +* You can implement this interface and call {@link LocationManager#addNmeaListener} +* to receive NMEA data from the GNSS engine. +*/ +public interface GnssNmeaListener { + /** Called when an NMEA message is received. */ + void onNmeaReceived(long timestamp, String nmea); +} \ No newline at end of file diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java new file mode 100644 index 0000000000000..77e8a5bbaca07 --- /dev/null +++ b/location/java/android/location/GnssStatus.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2016 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; + +/** + * This class represents the current state of the GNSS engine. + * This class is used in conjunction with the {@link GnssStatusCallback}. + */ +public final class GnssStatus { + /** Unknown constellation type. */ + public static final int CONSTELLATION_UNKNOWN = 0; + /** Constellation type constant for GPS. */ + public static final int CONSTELLATION_GPS = 1; + /** Constellation type constant for SBAS. */ + public static final int CONSTELLATION_SBAS = 2; + /** Constellation type constant for Glonass. */ + public static final int CONSTELLATION_GLONASS = 3; + /** Constellation type constant for QZSS. */ + public static final int CONSTELLATION_QZSS = 4; + /** Constellation type constant for Beidou. */ + public static final int CONSTELLATION_BEIDOU = 5; + /** Constellation type constant for Galileo. */ + public static final int CONSTELLATION_GALILEO = 6; + + // these must match the definitions in gps.h + /** @hide */ + public static final int GNSS_SV_FLAGS_NONE = 0; + /** @hide */ + public static final int GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA = (1 << 0); + /** @hide */ + public static final int GNSS_SV_FLAGS_HAS_ALMANAC_DATA = (1 << 1); + /** @hide */ + public static final int GNSS_SV_FLAGS_USED_IN_FIX = (1 << 2); + + /** @hide */ + public static final int PRN_SHIFT_WIDTH = 3; + + /* These package private values are modified by the LocationManager class */ + /* package */ int[] mPrnWithFlags; + /* package */ float[] mSnrs; + /* package */ float[] mElevations; + /* package */ float[] mAzimuths; + /* package */ int[] mConstellationTypes; + /* package */ int mSvCount; + + GnssStatus(int svCount, int[] prnWithFlags, float[] snrs, float[] elevations, float[] azimuths, + int[] constellationTypes) { + mSvCount = svCount; + mPrnWithFlags = prnWithFlags; + mSnrs = snrs; + mElevations = elevations; + mAzimuths = azimuths; + mConstellationTypes = constellationTypes; + } + + /** + * Gets the total number of satellites in satellite list. + */ + public int getNumSatellites() { + return mSvCount; + } + + /** + * Retrieves the constellation type of the satellite at the specified position. + * @param satIndex the index of the satellite in the list. + */ + public int getConstellationType(int satIndex) { + return mConstellationTypes[satIndex]; + } + + /** + * Retrieves the pseudo-random number of the satellite at the specified position. + * @param satIndex the index of the satellite in the list. + */ + public int getPrn(int satIndex) { + return mPrnWithFlags[satIndex] >> PRN_SHIFT_WIDTH; + } + + /** + * Retrieves the signal-noise ration of the satellite at the specified position. + * @param satIndex the index of the satellite in the list. + */ + public float getSnr(int satIndex) { + return mSnrs[satIndex]; + } + + /** + * Retrieves the elevation of the satellite at the specified position. + * @param satIndex the index of the satellite in the list. + */ + public float getElevation(int satIndex) { + return 0f; + } + + /** + * Retrieves the azimuth the satellite at the specified position. + * @param satIndex the index of the satellite in the list. + */ + public float getAzimuth(int satIndex) { + return mAzimuths[satIndex]; + } + + /** + * Detects whether the satellite at the specified position has ephemeris data. + * @param satIndex the index of the satellite in the list. + */ + public boolean hasEphemeris(int satIndex) { + return (mPrnWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0; + } + + /** + * Detects whether the satellite at the specified position has almanac data. + * @param satIndex the index of the satellite in the list. + */ + public boolean hasAlmanac(int satIndex) { + return (mPrnWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0; + } + + /** + * Detects whether the satellite at the specified position is used in fix. + * @param satIndex the index of the satellite in the list. + */ + public boolean usedInFix(int satIndex) { + return (mPrnWithFlags[satIndex] & GNSS_SV_FLAGS_USED_IN_FIX) != 0; + } +} diff --git a/location/java/android/location/GnssStatusCallback.java b/location/java/android/location/GnssStatusCallback.java new file mode 100644 index 0000000000000..b86171b35eefc --- /dev/null +++ b/location/java/android/location/GnssStatusCallback.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 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; + +/** + * Used for receiving notifications when GNSS events happen. + */ +public abstract class GnssStatusCallback { + /** + * Called when GNSS system has started. + */ + public void onStarted() {} + + /** + * Called when GNSS system has stopped. + */ + public void onStopped() {} + + /** + * Called when the GNSS system has received its first fix since starting. + * @param ttff the time from start to first fix. + */ + public void onFirstFix(int ttff) {} + + /** + * Called periodically to report GNSS satellite status. + * @param status the current status of all satellites. + */ + public void onSatelliteStatusChanged(GnssStatus status) {} +} \ No newline at end of file diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java index 323f3269368ef..8d2f781e497fd 100644 --- a/location/java/android/location/GpsStatus.java +++ b/location/java/android/location/GpsStatus.java @@ -34,17 +34,15 @@ public final class GpsStatus { private final SparseArray mSatellites = new SparseArray<>(); private final class SatelliteIterator implements Iterator { - - private final SparseArray mSatellites; private final int mSatellitesCount; private int mIndex = 0; - SatelliteIterator(SparseArray satellites) { - mSatellites = satellites; - mSatellitesCount = satellites.size(); + SatelliteIterator() { + mSatellitesCount = mSatellites.size(); } + @Override public boolean hasNext() { for (; mIndex < mSatellitesCount; ++mIndex) { GpsSatellite satellite = mSatellites.valueAt(mIndex); @@ -55,6 +53,7 @@ public final class GpsStatus { return false; } + @Override public GpsSatellite next() { while (mIndex < mSatellitesCount) { GpsSatellite satellite = mSatellites.valueAt(mIndex); @@ -66,14 +65,16 @@ public final class GpsStatus { throw new NoSuchElementException(); } + @Override public void remove() { throw new UnsupportedOperationException(); } } private Iterable mSatelliteList = new Iterable() { + @Override public Iterator iterator() { - return new SatelliteIterator(mSatellites); + return new SatelliteIterator(); } }; @@ -137,18 +138,15 @@ public final class GpsStatus { // For API-compat a public ctor() is not available GpsStatus() {} - /** - * Used internally within {@link LocationManager} to copy GPS status - * data from the Location Manager Service to its cached GpsStatus instance. - * Is synchronized to ensure that GPS status updates are atomic. - */ - synchronized void setStatus(int svCount, int[] prns, float[] snrs, - float[] elevations, float[] azimuths, int ephemerisMask, - int almanacMask, int usedInFixMask) { + private void setStatus(int svCount, int[] prnWithFlags, float[] snrs, float[] elevations, + float[] azimuths, int[] constellationTypes) { clearSatellites(); for (int i = 0; i < svCount; i++) { - int prn = prns[i]; - int prnShift = (1 << (prn - 1)); + // Skip all non-GPS satellites. + if (constellationTypes[i] != GnssStatus.CONSTELLATION_GPS) { + continue; + } + int prn = prnWithFlags[i] >> GnssStatus.PRN_SHIFT_WIDTH; if (prn > 0 && prn <= NUM_SATELLITES) { GpsSatellite satellite = mSatellites.get(prn); if (satellite == null) { @@ -160,53 +158,26 @@ public final class GpsStatus { satellite.mSnr = snrs[i]; satellite.mElevation = elevations[i]; satellite.mAzimuth = azimuths[i]; - satellite.mHasEphemeris = ((ephemerisMask & prnShift) != 0); - satellite.mHasAlmanac = ((almanacMask & prnShift) != 0); - satellite.mUsedInFix = ((usedInFixMask & prnShift) != 0); + satellite.mHasEphemeris = + (prnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0; + satellite.mHasAlmanac = + (prnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0; + satellite.mUsedInFix = + (prnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0; } } } /** - * Used by {@link LocationManager#getGpsStatus} to copy LocationManager's - * cached GpsStatus instance to the client's copy. + * Copies GPS satellites information from GnssStatus object. * Since this method is only used within {@link LocationManager#getGpsStatus}, * it does not need to be synchronized. + * @hide */ - void setStatus(GpsStatus status) { - mTimeToFirstFix = status.getTimeToFirstFix(); - clearSatellites(); - - SparseArray otherSatellites = status.mSatellites; - int otherSatellitesCount = otherSatellites.size(); - int satelliteIndex = 0; - // merge both sparse arrays, note that we have already invalidated the elements in the - // receiver array - for (int i = 0; i < otherSatellitesCount; ++i) { - GpsSatellite otherSatellite = otherSatellites.valueAt(i); - int otherSatellitePrn = otherSatellite.getPrn(); - - int satellitesCount = mSatellites.size(); - while (satelliteIndex < satellitesCount - && mSatellites.valueAt(satelliteIndex).getPrn() < otherSatellitePrn) { - ++satelliteIndex; - } - - if (satelliteIndex < mSatellites.size()) { - GpsSatellite satellite = mSatellites.valueAt(satelliteIndex); - if (satellite.getPrn() == otherSatellitePrn) { - satellite.setStatus(otherSatellite); - } else { - satellite = new GpsSatellite(otherSatellitePrn); - satellite.setStatus(otherSatellite); - mSatellites.put(otherSatellitePrn, satellite); - } - } else { - GpsSatellite satellite = new GpsSatellite(otherSatellitePrn); - satellite.setStatus(otherSatellite); - mSatellites.append(otherSatellitePrn, satellite); - } - } + void setStatus(GnssStatus status, int timeToFirstFix) { + mTimeToFirstFix = timeToFirstFix; + setStatus(status.mSvCount, status.mPrnWithFlags, status.mSnrs, status.mElevations, + status.mAzimuths, status.mConstellationTypes); } void setTimeToFirstFix(int ttff) { diff --git a/location/java/android/location/IGpsStatusListener.aidl b/location/java/android/location/IGnssStatusListener.aidl similarity index 73% rename from location/java/android/location/IGpsStatusListener.aidl rename to location/java/android/location/IGnssStatusListener.aidl index 62b1c6b9b35c1..d1c6a85a9fdd1 100644 --- a/location/java/android/location/IGpsStatusListener.aidl +++ b/location/java/android/location/IGnssStatusListener.aidl @@ -21,13 +21,12 @@ import android.location.Location; /** * {@hide} */ -oneway interface IGpsStatusListener +oneway interface IGnssStatusListener { - void onGpsStarted(); - void onGpsStopped(); + void onGnssStarted(); + void onGnssStopped(); void onFirstFix(int ttff); - void onSvStatusChanged(int svCount, in int[] prns, in float[] snrs, - in float[] elevations, in float[] azimuths, - int ephemerisMask, int almanacMask, int usedInFixMask); + void onSvStatusChanged(int svCount, in int[] prnWithFlags, in float[] snrs, + in float[] elevations, in float[] azimuths, in int[] constellationTypes); void onNmeaReceived(long timestamp, String nmea); } diff --git a/location/java/android/location/IGpsStatusProvider.aidl b/location/java/android/location/IGnssStatusProvider.aidl similarity index 69% rename from location/java/android/location/IGpsStatusProvider.aidl rename to location/java/android/location/IGnssStatusProvider.aidl index cf277c8c5d01d..006b5d3c0c20a 100644 --- a/location/java/android/location/IGpsStatusProvider.aidl +++ b/location/java/android/location/IGnssStatusProvider.aidl @@ -16,14 +16,14 @@ package android.location; -import android.location.IGpsStatusListener; +import android.location.IGnssStatusListener; /** - * An interface for location providers that provide GPS status information. + * An interface for location providers that provide GNSS status information. * * {@hide} */ -interface IGpsStatusProvider { - void addGpsStatusListener(IGpsStatusListener listener); - void removeGpsStatusListener(IGpsStatusListener listener); +interface IGnssStatusProvider { + void registerGnssStatusCallback(IGnssStatusListener callback); + void unregisterGnssStatusCallback(IGnssStatusListener callback); } diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index f3d755ce34e87..34e7a1a4a0638 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -21,9 +21,9 @@ import android.location.Address; import android.location.Criteria; import android.location.GeocoderParams; import android.location.Geofence; +import android.location.IGnssStatusListener; import android.location.IGpsMeasurementsListener; import android.location.IGpsNavigationMessageListener; -import android.location.IGpsStatusListener; import android.location.ILocationListener; import android.location.Location; import android.location.LocationRequest; @@ -48,8 +48,8 @@ interface ILocationManager Location getLastLocation(in LocationRequest request, String packageName); - boolean addGpsStatusListener(IGpsStatusListener listener, String packageName); - void removeGpsStatusListener(IGpsStatusListener listener); + boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName); + void unregisterGnssStatusCallback(IGnssStatusListener callback); boolean geocoderIsPresent(); String getFromLocation(double latitude, double longitude, int maxResults, diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 2c1932439584c..d35d5297d03db 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -65,11 +65,16 @@ public class LocationManager { private final ILocationManager mService; private final GpsMeasurementListenerTransport mGpsMeasurementListenerTransport; private final GpsNavigationMessageListenerTransport mGpsNavigationMessageListenerTransport; - private final HashMap mGpsStatusListeners = - new HashMap(); - private final HashMap mNmeaListeners = - new HashMap(); - private final GpsStatus mGpsStatus = new GpsStatus(); + private final HashMap mGpsStatusListeners = + new HashMap<>(); + private final HashMap mGpsNmeaListeners = + new HashMap<>(); + private final HashMap mGnssStatusListeners = + new HashMap<>(); + private final HashMap mGnssNmeaListeners = + new HashMap<>(); + private GnssStatus mGnssStatus; + private int mTimeToFirstFix; /** * Name of the network location provider. @@ -1389,11 +1394,51 @@ public class LocationManager { // --- GPS-specific support --- - // This class is used to send GPS status events to the client's main thread. - private class GpsStatusListenerTransport extends IGpsStatusListener.Stub { + // This class is used to send Gnss status events to the client's specific thread. + private class GnssStatusListenerTransport extends IGnssStatusListener.Stub { - private final GpsStatus.Listener mListener; - private final GpsStatus.NmeaListener mNmeaListener; + private final GpsStatus.Listener mGpsListener; + private final GpsStatus.NmeaListener mGpsNmeaListener; + private final GnssStatusCallback mGnssCallback; + private final GnssNmeaListener mGnssNmeaListener; + + private class GnssHandler extends Handler { + public GnssHandler(Handler handler) { + super(handler != null ? handler.getLooper() : Looper.myLooper()); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case NMEA_RECEIVED: + synchronized (mNmeaBuffer) { + int length = mNmeaBuffer.size(); + for (int i = 0; i < length; i++) { + Nmea nmea = mNmeaBuffer.get(i); + mGnssNmeaListener.onNmeaReceived(nmea.mTimestamp, nmea.mNmea); + } + mNmeaBuffer.clear(); + } + break; + case GpsStatus.GPS_EVENT_STARTED: + mGnssCallback.onStarted(); + break; + case GpsStatus.GPS_EVENT_STOPPED: + mGnssCallback.onStopped(); + break; + case GpsStatus.GPS_EVENT_FIRST_FIX: + mGnssCallback.onFirstFix(mTimeToFirstFix); + break; + case GpsStatus.GPS_EVENT_SATELLITE_STATUS: + mGnssCallback.onSatelliteStatusChanged(mGnssStatus); + break; + default: + break; + } + } + } + + private final Handler mGnssHandler; // This must not equal any of the GpsStatus event IDs private static final int NMEA_RECEIVED = 1000; @@ -1407,97 +1452,141 @@ public class LocationManager { mNmea = nmea; } } - private ArrayList mNmeaBuffer; + private final ArrayList mNmeaBuffer; - GpsStatusListenerTransport(GpsStatus.Listener listener) { - mListener = listener; - mNmeaListener = null; + GnssStatusListenerTransport(GpsStatus.Listener listener) { + this(listener, null); } - GpsStatusListenerTransport(GpsStatus.NmeaListener listener) { - mNmeaListener = listener; - mListener = null; + GnssStatusListenerTransport(GpsStatus.Listener listener, Handler handler) { + mGpsListener = listener; + mGnssHandler = new GnssHandler(handler); + mGpsNmeaListener = null; + mNmeaBuffer = null; + mGnssCallback = new GnssStatusCallback() { + @Override + public void onStarted() { + mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_STARTED); + } + + @Override + public void onStopped() { + mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_STOPPED); + } + + @Override + public void onFirstFix(int ttff) { + mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_FIRST_FIX); + } + + @Override + public void onSatelliteStatusChanged(GnssStatus status) { + mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_SATELLITE_STATUS); + } + }; + mGnssNmeaListener = null; + } + + GnssStatusListenerTransport(GpsStatus.NmeaListener listener) { + this(listener, null); + } + + GnssStatusListenerTransport(GpsStatus.NmeaListener listener, Handler handler) { + mGpsListener = null; + mGnssHandler = new GnssHandler(handler); + mGpsNmeaListener = listener; + mNmeaBuffer = new ArrayList(); + mGnssCallback = null; + mGnssNmeaListener = new GnssNmeaListener() { + @Override + public void onNmeaReceived(long timestamp, String nmea) { + mGpsNmeaListener.onNmeaReceived(timestamp, nmea); + } + }; + } + + GnssStatusListenerTransport(GnssStatusCallback callback) { + this(callback, null); + } + + GnssStatusListenerTransport(GnssStatusCallback callback, Handler handler) { + mGnssCallback = callback; + mGnssHandler = new GnssHandler(handler); + mGnssNmeaListener = null; + mNmeaBuffer = null; + mGpsListener = null; + mGpsNmeaListener = null; + } + + GnssStatusListenerTransport(GnssNmeaListener listener) { + this(listener, null); + } + + GnssStatusListenerTransport(GnssNmeaListener listener, Handler handler) { + mGnssCallback = null; + mGnssHandler = new GnssHandler(handler); + mGnssNmeaListener = listener; + mGpsListener = null; + mGpsNmeaListener = null; mNmeaBuffer = new ArrayList(); } @Override - public void onGpsStarted() { - if (mListener != null) { + public void onGnssStarted() { + if (mGpsListener != null) { Message msg = Message.obtain(); msg.what = GpsStatus.GPS_EVENT_STARTED; - mGpsHandler.sendMessage(msg); + mGnssHandler.sendMessage(msg); } } @Override - public void onGpsStopped() { - if (mListener != null) { + public void onGnssStopped() { + if (mGpsListener != null) { Message msg = Message.obtain(); msg.what = GpsStatus.GPS_EVENT_STOPPED; - mGpsHandler.sendMessage(msg); + mGnssHandler.sendMessage(msg); } } @Override public void onFirstFix(int ttff) { - if (mListener != null) { - mGpsStatus.setTimeToFirstFix(ttff); + if (mGpsListener != null) { + mTimeToFirstFix = ttff; Message msg = Message.obtain(); msg.what = GpsStatus.GPS_EVENT_FIRST_FIX; - mGpsHandler.sendMessage(msg); + mGnssHandler.sendMessage(msg); } } @Override - public void onSvStatusChanged(int svCount, int[] prns, float[] snrs, - float[] elevations, float[] azimuths, int ephemerisMask, - int almanacMask, int usedInFixMask) { - if (mListener != null) { - mGpsStatus.setStatus(svCount, prns, snrs, elevations, azimuths, - ephemerisMask, almanacMask, usedInFixMask); + public void onSvStatusChanged(int svCount, int[] prnWithFlags, + float[] snrs, float[] elevations, float[] azimuths, int[] constellationTypes) { + if (mGnssCallback != null) { + mGnssStatus = new GnssStatus(svCount, prnWithFlags, snrs, elevations, azimuths, + constellationTypes); 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); + mGnssHandler.removeMessages(GpsStatus.GPS_EVENT_SATELLITE_STATUS); + mGnssHandler.sendMessage(msg); } } @Override public void onNmeaReceived(long timestamp, String nmea) { - if (mNmeaListener != null) { + if (mGnssNmeaListener != 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); + mGnssHandler.removeMessages(NMEA_RECEIVED); + mGnssHandler.sendMessage(msg); } } - - private final Handler mGpsHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - 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); - } - } - } - }; } /** @@ -1508,7 +1597,9 @@ public class LocationManager { * @return true if the listener was successfully added * * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present + * @deprecated use {@link #registerGnssStatusCallback(GnssStatusCallback)} instead. */ + @Deprecated @RequiresPermission(ACCESS_FINE_LOCATION) public boolean addGpsStatusListener(GpsStatus.Listener listener) { boolean result; @@ -1518,8 +1609,8 @@ public class LocationManager { return true; } try { - GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener); - result = mService.addGpsStatusListener(transport, mContext.getPackageName()); + GnssStatusListenerTransport transport = new GnssStatusListenerTransport(listener); + result = mService.registerGnssStatusCallback(transport, mContext.getPackageName()); if (result) { mGpsStatusListeners.put(listener, transport); } @@ -1536,17 +1627,81 @@ public class LocationManager { * * @param listener GPS status listener object to remove */ + @Deprecated public void removeGpsStatusListener(GpsStatus.Listener listener) { try { - GpsStatusListenerTransport transport = mGpsStatusListeners.remove(listener); + GnssStatusListenerTransport transport = mGpsStatusListeners.remove(listener); if (transport != null) { - mService.removeGpsStatusListener(transport); + mService.unregisterGnssStatusCallback(transport); } } catch (RemoteException e) { Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e); } } + + /** + * Registers a GNSS status listener. + * + * @param callback GNSS status listener object to register + * + * @return true if the listener was successfully added + * + * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present + */ + @RequiresPermission(ACCESS_FINE_LOCATION) + public boolean registerGnssStatusCallback(GnssStatusCallback callback) { + return registerGnssStatusCallback(callback, null); + } + + /** + * Registers a GNSS status listener. + * + * @param callback GNSS status listener object to register + * @param handler the handler that the callback runs on. + * + * @return true if the listener was successfully added + * + * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present + */ + @RequiresPermission(ACCESS_FINE_LOCATION) + public boolean registerGnssStatusCallback(GnssStatusCallback callback, Handler handler) { + boolean result; + if (mGnssStatusListeners.get(callback) != null) { + // listener is already registered + return true; + } + try { + GnssStatusListenerTransport transport = + new GnssStatusListenerTransport(callback, handler); + result = mService.registerGnssStatusCallback(transport, mContext.getPackageName()); + if (result) { + mGnssStatusListeners.put(callback, transport); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in registerGnssStatusCallback: ", e); + result = false; + } + + return result; + } + + /** + * Removes a GNSS status listener. + * + * @param callback GNSS status listener object to remove + */ + public void unregisterGnssStatusCallback(GnssStatusCallback callback) { + try { + GnssStatusListenerTransport transport = mGnssStatusListeners.remove(callback); + if (transport != null) { + mService.unregisterGnssStatusCallback(transport); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in unregisterGnssStatusCallback: ", e); + } + } + /** * Adds an NMEA listener. * @@ -1555,20 +1710,22 @@ public class LocationManager { * @return true if the listener was successfully added * * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present + * @deprecated use {@link #addNmeaListener(GnssNmeaListener)} instead. */ + @Deprecated @RequiresPermission(ACCESS_FINE_LOCATION) public boolean addNmeaListener(GpsStatus.NmeaListener listener) { boolean result; - if (mNmeaListeners.get(listener) != null) { + if (mGpsNmeaListeners.get(listener) != null) { // listener is already registered return true; } try { - GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener); - result = mService.addGpsStatusListener(transport, mContext.getPackageName()); + GnssStatusListenerTransport transport = new GnssStatusListenerTransport(listener); + result = mService.registerGnssStatusCallback(transport, mContext.getPackageName()); if (result) { - mNmeaListeners.put(listener, transport); + mGpsNmeaListeners.put(listener, transport); } } catch (RemoteException e) { Log.e(TAG, "RemoteException in registerGpsStatusListener: ", e); @@ -1583,17 +1740,81 @@ public class LocationManager { * * @param listener a {@link GpsStatus.NmeaListener} object to remove */ + @Deprecated public void removeNmeaListener(GpsStatus.NmeaListener listener) { try { - GpsStatusListenerTransport transport = mNmeaListeners.remove(listener); + GnssStatusListenerTransport transport = mGpsNmeaListeners.remove(listener); if (transport != null) { - mService.removeGpsStatusListener(transport); + mService.unregisterGnssStatusCallback(transport); } } catch (RemoteException e) { Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e); } } + /** + * Adds an NMEA listener. + * + * @param listener a {@link GnssNmeaListener} object to register + * + * @return true if the listener was successfully added + * + * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present + */ + @RequiresPermission(ACCESS_FINE_LOCATION) + public boolean addNmeaListener(GnssNmeaListener listener) { + return addNmeaListener(listener, null); + } + + /** + * Adds an NMEA listener. + * + * @param listener a {@link GnssNmeaListener} object to register + * @param handler the handler that the listener runs on. + * + * @return true if the listener was successfully added + * + * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present + */ + @RequiresPermission(ACCESS_FINE_LOCATION) + public boolean addNmeaListener(GnssNmeaListener listener, Handler handler) { + boolean result; + + if (mGpsNmeaListeners.get(listener) != null) { + // listener is already registered + return true; + } + try { + GnssStatusListenerTransport transport = + new GnssStatusListenerTransport(listener, handler); + result = mService.registerGnssStatusCallback(transport, mContext.getPackageName()); + if (result) { + mGnssNmeaListeners.put(listener, transport); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in registerGnssStatusCallback: ", e); + result = false; + } + + return result; + } + + /** + * Removes an NMEA listener. + * + * @param listener a {@link GnssNmeaListener} object to remove + */ + public void removeNmeaListener(GnssNmeaListener listener) { + try { + GnssStatusListenerTransport transport = mGnssNmeaListeners.remove(listener); + if (transport != null) { + mService.unregisterGnssStatusCallback(transport); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in unregisterGnssStatusCallback: ", e); + } + } + /** * Adds a GPS Measurement listener. * @@ -1656,11 +1877,16 @@ public class LocationManager { * @param status object containing GPS status details, or null. * @return status object containing updated GPS status. */ + @Deprecated public GpsStatus getGpsStatus(GpsStatus status) { if (status == null) { status = new GpsStatus(); } - status.setStatus(mGpsStatus); + // When mGnssStatus is null, that means that this method is called outside + // onGpsStatusChanged(). Return an empty status to maintain backwards compatibility. + if (mGnssStatus != null) { + status.setStatus(mGnssStatus, mTimeToFirstFix); + } return status; } diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java index 260f380d93e90..93e86afe2589c 100644 --- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java +++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java @@ -62,7 +62,7 @@ public class GpsNetInitiatedHandler { public static final String NI_INTENT_KEY_TIMEOUT = "timeout"; public static final String NI_INTENT_KEY_DEFAULT_RESPONSE = "default_resp"; - // the extra command to send NI response to GpsLocationProvider + // the extra command to send NI response to GnssLocationProvider public static final String NI_RESPONSE_EXTRA_CMD = "send_ni_response"; // the extra command parameter names in the Bundle diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 9405d8e05c5e7..dc4309c0e0175 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -24,10 +24,10 @@ import com.android.internal.os.BackgroundThread; import com.android.server.location.ActivityRecognitionProxy; import com.android.server.location.FlpHardwareProvider; import com.android.server.location.FusedProxy; +import com.android.server.location.GnssLocationProvider; import com.android.server.location.GeocoderProxy; import com.android.server.location.GeofenceManager; import com.android.server.location.GeofenceProxy; -import com.android.server.location.GpsLocationProvider; import com.android.server.location.GpsMeasurementsProvider; import com.android.server.location.GpsNavigationMessageProvider; import com.android.server.location.LocationBlacklist; @@ -61,11 +61,11 @@ import android.location.Address; import android.location.Criteria; import android.location.GeocoderParams; import android.location.Geofence; +import android.location.IGnssStatusListener; +import android.location.IGnssStatusProvider; import android.location.IGpsGeofenceHardware; import android.location.IGpsMeasurementsListener; import android.location.IGpsNavigationMessageListener; -import android.location.IGpsStatusListener; -import android.location.IGpsStatusProvider; import android.location.ILocationListener; import android.location.ILocationManager; import android.location.INetInitiatedListener; @@ -157,7 +157,7 @@ public class LocationManagerService extends ILocationManager.Stub { private PowerManager mPowerManager; private UserManager mUserManager; private GeocoderProxy mGeocodeProvider; - private IGpsStatusProvider mGpsStatusProvider; + private IGnssStatusProvider mGnssStatusProvider; private INetInitiatedListener mNetInitiatedListener; private LocationWorkerHandler mLocationHandler; private PassiveProvider mPassiveProvider; // track passive provider for special cases @@ -456,17 +456,17 @@ public class LocationManagerService extends ILocationManager.Stub { mEnabledProviders.add(passiveProvider.getName()); mPassiveProvider = passiveProvider; - if (GpsLocationProvider.isSupported()) { + if (GnssLocationProvider.isSupported()) { // Create a gps location provider - GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this, + GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this, mLocationHandler.getLooper()); - mGpsStatusProvider = gpsProvider.getGpsStatusProvider(); - mNetInitiatedListener = gpsProvider.getNetInitiatedListener(); - addProviderLocked(gpsProvider); - mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider); - mGpsMeasurementsProvider = gpsProvider.getGpsMeasurementsProvider(); - mGpsNavigationMessageProvider = gpsProvider.getGpsNavigationMessageProvider(); - mGpsGeofenceProxy = gpsProvider.getGpsGeofenceProxy(); + mGnssStatusProvider = gnssProvider.getGnssStatusProvider(); + mNetInitiatedListener = gnssProvider.getNetInitiatedListener(); + addProviderLocked(gnssProvider); + mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider); + mGpsMeasurementsProvider = gnssProvider.getGpsMeasurementsProvider(); + mGpsNavigationMessageProvider = gnssProvider.getGpsNavigationMessageProvider(); + mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy(); } /* @@ -1867,7 +1867,7 @@ public class LocationManagerService extends ILocationManager.Stub { @Override - public boolean addGpsStatusListener(IGpsStatusListener listener, String packageName) { + public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) { int allowedResolutionLevel = getCallerAllowedResolutionLevel(); checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, LocationManager.GPS_PROVIDER); @@ -1883,26 +1883,26 @@ public class LocationManagerService extends ILocationManager.Stub { Binder.restoreCallingIdentity(ident); } - if (mGpsStatusProvider == null) { + if (mGnssStatusProvider == null) { return false; } try { - mGpsStatusProvider.addGpsStatusListener(listener); + mGnssStatusProvider.registerGnssStatusCallback(callback); } catch (RemoteException e) { - Slog.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e); + Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e); return false; } return true; } @Override - public void removeGpsStatusListener(IGpsStatusListener listener) { + public void unregisterGnssStatusCallback(IGnssStatusListener callback) { synchronized (mLock) { try { - mGpsStatusProvider.removeGpsStatusListener(listener); + mGnssStatusProvider.unregisterGnssStatusCallback(callback); } catch (Exception e) { - Slog.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e); + Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e); } } } diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java similarity index 97% rename from services/core/java/com/android/server/location/GpsLocationProvider.java rename to services/core/java/com/android/server/location/GnssLocationProvider.java index 88ab2c65e979e..022f1b31be461 100644 --- a/services/core/java/com/android/server/location/GpsLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -35,11 +35,12 @@ import android.hardware.location.GeofenceHardware; import android.hardware.location.GeofenceHardwareImpl; import android.location.Criteria; import android.location.FusedBatchOptions; +import android.location.GnssStatus; +import android.location.IGnssStatusListener; +import android.location.IGnssStatusProvider; import android.location.GpsMeasurementsEvent; import android.location.GpsNavigationMessageEvent; import android.location.IGpsGeofenceHardware; -import android.location.IGpsStatusListener; -import android.location.IGpsStatusProvider; import android.location.ILocationManager; import android.location.INetInitiatedListener; import android.location.Location; @@ -100,9 +101,9 @@ import libcore.io.IoUtils; * * {@hide} */ -public class GpsLocationProvider implements LocationProviderInterface { +public class GnssLocationProvider implements LocationProviderInterface { - private static final String TAG = "GpsLocationProvider"; + private static final String TAG = "GnssLocationProvider"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); @@ -366,7 +367,7 @@ public class GpsLocationProvider implements LocationProviderInterface { private final ILocationManager mILocationManager; private Location mLocation = new Location(LocationManager.GPS_PROVIDER); private Bundle mLocationExtras = new Bundle(); - private final GpsStatusListenerHelper mListenerHelper; + private final GnssStatusListenerHelper mListenerHelper; private final GpsMeasurementsProvider mGpsMeasurementsProvider; private final GpsNavigationMessageProvider mGpsNavigationMessageProvider; @@ -382,7 +383,7 @@ public class GpsLocationProvider implements LocationProviderInterface { private final GpsNetInitiatedHandler mNIHandler; // Wakelocks - private final static String WAKELOCK_KEY = "GpsLocationProvider"; + private final static String WAKELOCK_KEY = "GnssLocationProvider"; private final PowerManager.WakeLock mWakeLock; // Alarms @@ -405,20 +406,20 @@ public class GpsLocationProvider implements LocationProviderInterface { private GeofenceHardwareImpl mGeofenceHardwareImpl; - private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() { + private final IGnssStatusProvider mGnssStatusProvider = new IGnssStatusProvider.Stub() { @Override - public void addGpsStatusListener(IGpsStatusListener listener) { - mListenerHelper.addListener(listener); + public void registerGnssStatusCallback(IGnssStatusListener callback) { + mListenerHelper.addListener(callback); } @Override - public void removeGpsStatusListener(IGpsStatusListener listener) { - mListenerHelper.removeListener(listener); + public void unregisterGnssStatusCallback(IGnssStatusListener callback) { + mListenerHelper.removeListener(callback); } }; - public IGpsStatusProvider getGpsStatusProvider() { - return mGpsStatusProvider; + public IGnssStatusProvider getGnssStatusProvider() { + return mGnssStatusProvider; } public IGpsGeofenceHardware getGpsGeofenceProxy() { @@ -655,7 +656,7 @@ public class GpsLocationProvider implements LocationProviderInterface { return true; } - public GpsLocationProvider(Context context, ILocationManager ilocationManager, + public GnssLocationProvider(Context context, ILocationManager ilocationManager, Looper looper) { mContext = context; mNtpTime = NtpTrustedTime.getInstance(context); @@ -698,7 +699,7 @@ public class GpsLocationProvider implements LocationProviderInterface { mNetInitiatedListener, mSuplEsEnabled); - mListenerHelper = new GpsStatusListenerHelper(mHandler) { + mListenerHelper = new GnssStatusListenerHelper(mHandler) { @Override protected boolean isAvailableInPlatform() { return isSupported(); @@ -1554,34 +1555,40 @@ public class GpsLocationProvider implements LocationProviderInterface { * called from native code to update SV info */ private void reportSvStatus() { - int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks); + int svCount = native_read_sv_status(mPrnWithFlags, mSnrs, mSvElevations, mSvAzimuths, + mConstellationTypes); mListenerHelper.onSvStatusChanged( svCount, - mSvs, + mPrnWithFlags, mSnrs, mSvElevations, mSvAzimuths, - mSvMasks[EPHEMERIS_MASK], - mSvMasks[ALMANAC_MASK], - mSvMasks[USED_FOR_FIX_MASK]); + mConstellationTypes); if (VERBOSE) { - Log.v(TAG, "SV count: " + svCount + - " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) + - " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK])); - for (int i = 0; i < svCount; i++) { - Log.v(TAG, "sv: " + mSvs[i] + + Log.v(TAG, "SV count: " + svCount); + } + // Calculate number of sets used in fix. + int usedInFixCount = 0; + for (int i = 0; i < svCount; i++) { + if ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0) { + ++usedInFixCount; + } + if (VERBOSE) { + Log.v(TAG, "prn: " + (mPrnWithFlags[i] >> GnssStatus.PRN_SHIFT_WIDTH) + " snr: " + mSnrs[i]/10 + " elev: " + mSvElevations[i] + " azimuth: " + mSvAzimuths[i] + - ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " E") + - ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " A") + - ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U")); + ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0 + ? " " : " E") + + ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) == 0 + ? " " : " A") + + ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) == 0 + ? "" : "U")); } } - // return number of sets used in fix instead of total - updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK])); + updateStatus(mStatus, usedInFixCount); if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 && System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) { @@ -2067,7 +2074,7 @@ public class GpsLocationProvider implements LocationProviderInterface { } /** - * This method is bound to {@link #GpsLocationProvider(Context, ILocationManager, Looper)}. + * This method is bound to {@link #GnssLocationProvider(Context, ILocationManager, Looper)}. * It is in charge of loading properties and registering for events that will be posted to * this handler. */ @@ -2362,17 +2369,14 @@ public class GpsLocationProvider implements LocationProviderInterface { } // for GPS SV statistics - private static final int MAX_SVS = 32; - private static final int EPHEMERIS_MASK = 0; - private static final int ALMANAC_MASK = 1; - private static final int USED_FOR_FIX_MASK = 2; + private static final int MAX_SVS = 512; // preallocated arrays, to avoid memory allocation in reportStatus() - private int mSvs[] = new int[MAX_SVS]; + private int mPrnWithFlags[] = new int[MAX_SVS]; private float mSnrs[] = new float[MAX_SVS]; private float mSvElevations[] = new float[MAX_SVS]; private float mSvAzimuths[] = new float[MAX_SVS]; - private int mSvMasks[] = new int[3]; + private int mConstellationTypes[] = new int[MAX_SVS]; private int mSvCount; // preallocated to avoid memory allocation in reportNmea() private byte[] mNmeaBuffer = new byte[120]; @@ -2392,8 +2396,8 @@ public class GpsLocationProvider implements LocationProviderInterface { private native void native_delete_aiding_data(int flags); // returns number of SVs // 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_sv_status(int[] prnWithFlags, float[] snrs, float[] elevations, + float[] azimuths, int[] constellationTypes); private native int native_read_nmea(byte[] buffer, int bufferSize); private native void native_inject_location(double latitude, double longitude, float accuracy); diff --git a/services/core/java/com/android/server/location/GpsStatusListenerHelper.java b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java similarity index 62% rename from services/core/java/com/android/server/location/GpsStatusListenerHelper.java rename to services/core/java/com/android/server/location/GnssStatusListenerHelper.java index 53ff6c24ae6b7..9840c61ec516d 100644 --- a/services/core/java/com/android/server/location/GpsStatusListenerHelper.java +++ b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java @@ -16,17 +16,17 @@ package com.android.server.location; -import android.location.IGpsStatusListener; +import android.location.IGnssStatusListener; import android.os.Handler; import android.os.RemoteException; /** - * Implementation of a handler for {@link IGpsStatusListener}. + * Implementation of a handler for {@link IGnssStatusListener}. */ -abstract class GpsStatusListenerHelper extends RemoteListenerHelper { - protected GpsStatusListenerHelper(Handler handler) { - super(handler, "GpsStatusListenerHelper"); - setSupported(GpsLocationProvider.isSupported()); +abstract class GnssStatusListenerHelper extends RemoteListenerHelper { + protected GnssStatusListenerHelper(Handler handler) { + super(handler, "GnssStatusListenerHelper"); + setSupported(GnssLocationProvider.isSupported()); } @Override @@ -38,7 +38,7 @@ abstract class GpsStatusListenerHelper extends RemoteListenerHelper getHandlerOperation(int result) { + protected ListenerOperation getHandlerOperation(int result) { return null; } @@ -47,15 +47,15 @@ abstract class GpsStatusListenerHelper extends RemoteListenerHelper {} + private interface Operation extends ListenerOperation {} } diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk index 98d8d086e5117..d1b8648781098 100644 --- a/services/core/jni/Android.mk +++ b/services/core/jni/Android.mk @@ -22,7 +22,7 @@ LOCAL_SRC_FILES += \ $(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \ $(LOCAL_REL_DIR)/com_android_server_input_InputWindowHandle.cpp \ $(LOCAL_REL_DIR)/com_android_server_lights_LightsService.cpp \ - $(LOCAL_REL_DIR)/com_android_server_location_GpsLocationProvider.cpp \ + $(LOCAL_REL_DIR)/com_android_server_location_GnssLocationProvider.cpp \ $(LOCAL_REL_DIR)/com_android_server_location_FlpHardwareProvider.cpp \ $(LOCAL_REL_DIR)/com_android_server_power_PowerManagerService.cpp \ $(LOCAL_REL_DIR)/com_android_server_SerialService.cpp \ diff --git a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp similarity index 85% rename from services/core/jni/com_android_server_location_GpsLocationProvider.cpp rename to services/core/jni/com_android_server_location_GnssLocationProvider.cpp index b8d4196dad16f..f736cd554a166 100644 --- a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define LOG_TAG "GpsLocationProvider" +#define LOG_TAG "GnssLocationProvider" #define LOG_NDEBUG 0 @@ -67,8 +67,13 @@ static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL; static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL; static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL; +#define MAX_SATELLITE_COUNT 512 + +#define PRN_SHIFT_WIDTH 3 + // temporary storage for GPS callbacks -static GpsSvStatus sGpsSvStatus; +static GnssSvInfo sGnssSvList[MAX_SATELLITE_COUNT]; +static size_t sGnssSvListSize; static const char* sNmeaString; static int sNmeaStringLength; @@ -105,7 +110,50 @@ static void status_callback(GpsStatus* status) static void sv_status_callback(GpsSvStatus* sv_status) { JNIEnv* env = AndroidRuntime::getJNIEnv(); - memcpy(&sGpsSvStatus, sv_status, sizeof(sGpsSvStatus)); + size_t status_size = sv_status->size; + // Some drive doesn't set the size field correctly. Assume GpsSvStatus_v1 if + // it doesn't provide a valid size. + if (status_size == 0) { + status_size = sizeof(GpsSvStatus_v1); + } + if (sv_status->size == sizeof(GpsSvStatus_v2)) { + sGnssSvListSize = sv_status->gnss_sv_list_size; + // Cramp the list size + if (sGnssSvListSize > MAX_SATELLITE_COUNT) { + sGnssSvListSize = MAX_SATELLITE_COUNT; + } + // Copy GNSS SV info into sGnssSvList, if any. + if (sGnssSvListSize > 0 && sv_status->gnss_sv_list) { + memcpy(sGnssSvList, sv_status->gnss_sv_list, sizeof(GnssSvInfo) * sGnssSvListSize); + } + } else if (status_size == sizeof(GpsSvStatus_v1)) { + sGnssSvListSize = sv_status->num_svs; + uint32_t ephemeris_mask = sv_status->ephemeris_mask; + uint32_t almanac_mask = sv_status->almanac_mask; + uint32_t used_in_fix_mask = sv_status->used_in_fix_mask; + for (size_t i = 0; i < sGnssSvListSize; i++) { + GnssSvInfo& info = sGnssSvList[i]; + info.constellation = GNSS_CONSTELLATION_GPS; + info.prn = sv_status->sv_list[i].prn; + info.snr = sv_status->sv_list[i].snr; + info.elevation = sv_status->sv_list[i].elevation; + info.azimuth = sv_status->sv_list[i].azimuth; + info.flags = GNSS_SV_FLAGS_NONE; + if ((ephemeris_mask & (1 << (info.prn - 1))) != 0) { + info.flags |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA; + } + if ((almanac_mask & (1 << (info.prn - 1))) != 0) { + info.flags |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA; + } + if ((used_in_fix_mask & (1 << (info.prn - 1))) != 0) { + info.flags |= GNSS_SV_FLAGS_USED_IN_FIX; + } + } + } else { + sGnssSvListSize = 0; + ALOGE("Invalid size of GpsSvStatus found: %zd.", status_size); + return; + } env->CallVoidMethod(mCallbacksObj, method_reportSvStatus); checkAndClearExceptionFromCallback(env, __FUNCTION__); } @@ -162,6 +210,7 @@ GpsCallbacks sGpsCallbacks = { release_wakelock_callback, create_thread_callback, request_utc_time_callback, + NULL, }; static void xtra_download_request_callback() @@ -439,7 +488,7 @@ GpsGeofenceCallbacks sGpsGeofenceCallbacks = { create_thread_callback, }; -static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) { +static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) { int err; hw_module_t* module; @@ -509,13 +558,13 @@ static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, } } -static jboolean android_location_GpsLocationProvider_is_supported( +static jboolean android_location_GnssLocationProvider_is_supported( JNIEnv* /* env */, jclass /* clazz */) { return (sGpsInterface != NULL) ? JNI_TRUE : JNI_FALSE; } -static jboolean android_location_GpsLocationProvider_is_agps_ril_supported( +static jboolean android_location_GnssLocationProvider_is_agps_ril_supported( JNIEnv* /* env */, jclass /* clazz */) { return (sAGpsRilInterface != NULL) ? JNI_TRUE : JNI_FALSE; @@ -527,7 +576,7 @@ static jboolean android_location_gpsLocationProvider_is_gnss_configuration_suppo return (sGnssConfigurationInterface != NULL) ? JNI_TRUE : JNI_FALSE; } -static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj) +static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj) { // this must be set before calling into the HAL library if (!mCallbacksObj) @@ -553,13 +602,13 @@ static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject o return JNI_TRUE; } -static void android_location_GpsLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */) +static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */) { if (sGpsInterface) sGpsInterface->cleanup(); } -static jboolean android_location_GpsLocationProvider_set_position_mode(JNIEnv* /* env */, +static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */, jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy, jint preferred_time) { @@ -575,7 +624,7 @@ static jboolean android_location_GpsLocationProvider_set_position_mode(JNIEnv* / return JNI_FALSE; } -static jboolean android_location_GpsLocationProvider_start(JNIEnv* /* env */, jobject /* obj */) +static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */) { if (sGpsInterface) { if (sGpsInterface->start() == 0) { @@ -588,7 +637,7 @@ static jboolean android_location_GpsLocationProvider_start(JNIEnv* /* env */, jo return JNI_FALSE; } -static jboolean android_location_GpsLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */) +static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */) { if (sGpsInterface) { if (sGpsInterface->stop() == 0) { @@ -601,7 +650,7 @@ static jboolean android_location_GpsLocationProvider_stop(JNIEnv* /* env */, job return JNI_FALSE; } -static void android_location_GpsLocationProvider_delete_aiding_data(JNIEnv* /* env */, +static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */, jobject /* obj */, jint flags) { @@ -609,38 +658,36 @@ static void android_location_GpsLocationProvider_delete_aiding_data(JNIEnv* /* e sGpsInterface->delete_aiding_data(flags); } -static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */, - jintArray prnArray, jfloatArray snrArray, jfloatArray elevArray, jfloatArray azumArray, - jintArray maskArray) +static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */, + jintArray prnWithFlagArray, jfloatArray snrArray, jfloatArray elevArray, + jfloatArray azumArray, jintArray constellationTypeArray) { // this should only be called from within a call to reportSvStatus - - jint* prns = env->GetIntArrayElements(prnArray, 0); + jint* prnWithFlags = env->GetIntArrayElements(prnWithFlagArray, 0); jfloat* snrs = env->GetFloatArrayElements(snrArray, 0); jfloat* elev = env->GetFloatArrayElements(elevArray, 0); jfloat* azim = env->GetFloatArrayElements(azumArray, 0); - jint* mask = env->GetIntArrayElements(maskArray, 0); + jint* constellationTypes = env->GetIntArrayElements(constellationTypeArray, 0); - int num_svs = sGpsSvStatus.num_svs; - for (int i = 0; i < num_svs; i++) { - prns[i] = sGpsSvStatus.sv_list[i].prn; - snrs[i] = sGpsSvStatus.sv_list[i].snr; - elev[i] = sGpsSvStatus.sv_list[i].elevation; - azim[i] = sGpsSvStatus.sv_list[i].azimuth; + // GNSS SV info. + for (size_t i = 0; i < sGnssSvListSize; ++i) { + const GnssSvInfo& info = sGnssSvList[i]; + constellationTypes[i] = info.constellation; + prnWithFlags[i] = (info.prn << PRN_SHIFT_WIDTH) | info.flags; + snrs[i] = info.snr; + elev[i] = info.elevation; + azim[i] = info.azimuth; } - mask[0] = sGpsSvStatus.ephemeris_mask; - mask[1] = sGpsSvStatus.almanac_mask; - mask[2] = sGpsSvStatus.used_in_fix_mask; - env->ReleaseIntArrayElements(prnArray, prns, 0); + env->ReleaseIntArrayElements(prnWithFlagArray, prnWithFlags, 0); env->ReleaseFloatArrayElements(snrArray, snrs, 0); env->ReleaseFloatArrayElements(elevArray, elev, 0); env->ReleaseFloatArrayElements(azumArray, azim, 0); - env->ReleaseIntArrayElements(maskArray, mask, 0); - return (jint) num_svs; + env->ReleaseIntArrayElements(constellationTypeArray, constellationTypes, 0); + return (jint) sGnssSvListSize; } -static void android_location_GpsLocationProvider_agps_set_reference_location_cellid( +static void android_location_GnssLocationProvider_agps_set_reference_location_cellid( JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid) { AGpsRefLocation location; @@ -667,7 +714,7 @@ static void android_location_GpsLocationProvider_agps_set_reference_location_cel sAGpsRilInterface->set_ref_location(&location, sizeof(location)); } -static void android_location_GpsLocationProvider_agps_send_ni_message(JNIEnv* env, +static void android_location_GnssLocationProvider_agps_send_ni_message(JNIEnv* env, jobject /* obj */, jbyteArray ni_msg, jint size) { size_t sz; @@ -684,7 +731,7 @@ static void android_location_GpsLocationProvider_agps_send_ni_message(JNIEnv* en env->ReleaseByteArrayElements(ni_msg,b,0); } -static void android_location_GpsLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */, +static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */, jint type, jstring setid_string) { if (!sAGpsRilInterface) { @@ -697,7 +744,7 @@ static void android_location_GpsLocationProvider_agps_set_id(JNIEnv *env, jobjec env->ReleaseStringUTFChars(setid_string, setid); } -static jint android_location_GpsLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */, +static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */, jbyteArray nmeaArray, jint buffer_size) { // this should only be called from within a call to reportNmea @@ -710,27 +757,27 @@ static jint android_location_GpsLocationProvider_read_nmea(JNIEnv* env, jobject return (jint) length; } -static void android_location_GpsLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */, +static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */, jlong time, jlong timeReference, jint uncertainty) { if (sGpsInterface) sGpsInterface->inject_time(time, timeReference, uncertainty); } -static void android_location_GpsLocationProvider_inject_location(JNIEnv* /* env */, +static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */, jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy) { if (sGpsInterface) sGpsInterface->inject_location(latitude, longitude, accuracy); } -static jboolean android_location_GpsLocationProvider_supports_xtra( +static jboolean android_location_GnssLocationProvider_supports_xtra( JNIEnv* /* env */, jobject /* obj */) { return (sGpsXtraInterface != NULL) ? JNI_TRUE : JNI_FALSE; } -static void android_location_GpsLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */, +static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */, jbyteArray data, jint length) { if (!sGpsXtraInterface) { @@ -743,7 +790,7 @@ static void android_location_GpsLocationProvider_inject_xtra_data(JNIEnv* env, j env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT); } -static void android_location_GpsLocationProvider_agps_data_conn_open( +static void android_location_GnssLocationProvider_agps_data_conn_open( JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType) { if (!sAGpsInterface) { @@ -769,7 +816,7 @@ static void android_location_GpsLocationProvider_agps_data_conn_open( env->ReleaseStringUTFChars(apn, apnStr); } -static void android_location_GpsLocationProvider_agps_data_conn_closed(JNIEnv* /* env */, +static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */, jobject /* obj */) { if (!sAGpsInterface) { @@ -779,7 +826,7 @@ static void android_location_GpsLocationProvider_agps_data_conn_closed(JNIEnv* / sAGpsInterface->data_conn_closed(); } -static void android_location_GpsLocationProvider_agps_data_conn_failed(JNIEnv* /* env */, +static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */, jobject /* obj */) { if (!sAGpsInterface) { @@ -789,7 +836,7 @@ static void android_location_GpsLocationProvider_agps_data_conn_failed(JNIEnv* / sAGpsInterface->data_conn_failed(); } -static void android_location_GpsLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */, +static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */, jint type, jstring hostname, jint port) { if (!sAGpsInterface) { @@ -801,7 +848,7 @@ static void android_location_GpsLocationProvider_set_agps_server(JNIEnv* env, jo env->ReleaseStringUTFChars(hostname, c_hostname); } -static void android_location_GpsLocationProvider_send_ni_response(JNIEnv* /* env */, +static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */, jobject /* obj */, jint notifId, jint response) { if (!sGpsNiInterface) { @@ -812,7 +859,7 @@ static void android_location_GpsLocationProvider_send_ni_response(JNIEnv* /* env sGpsNiInterface->respond(notifId, response); } -static jstring android_location_GpsLocationProvider_get_internal_state(JNIEnv* env, +static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env, jobject /* obj */) { jstring result = NULL; if (sGpsDebugInterface) { @@ -826,7 +873,7 @@ static jstring android_location_GpsLocationProvider_get_internal_state(JNIEnv* e return result; } -static void android_location_GpsLocationProvider_update_network_state(JNIEnv* env, jobject /* obj */, +static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env, jobject /* obj */, jboolean connected, jint type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn) { @@ -849,13 +896,13 @@ static void android_location_GpsLocationProvider_update_network_state(JNIEnv* en } } -static jboolean android_location_GpsLocationProvider_is_geofence_supported( +static jboolean android_location_GnssLocationProvider_is_geofence_supported( JNIEnv* /* env */, jobject /* obj */) { return (sGpsGeofencingInterface != NULL) ? JNI_TRUE : JNI_FALSE; } -static jboolean android_location_GpsLocationProvider_add_geofence(JNIEnv* /* env */, +static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */, jobject /* obj */, jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius, jint last_transition, jint monitor_transition, jint notification_responsiveness, jint unknown_timer) { @@ -870,7 +917,7 @@ static jboolean android_location_GpsLocationProvider_add_geofence(JNIEnv* /* env return JNI_FALSE; } -static jboolean android_location_GpsLocationProvider_remove_geofence(JNIEnv* /* env */, +static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */, jobject /* obj */, jint geofence_id) { if (sGpsGeofencingInterface != NULL) { sGpsGeofencingInterface->remove_geofence_area(geofence_id); @@ -881,7 +928,7 @@ static jboolean android_location_GpsLocationProvider_remove_geofence(JNIEnv* /* return JNI_FALSE; } -static jboolean android_location_GpsLocationProvider_pause_geofence(JNIEnv* /* env */, +static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */, jobject /* obj */, jint geofence_id) { if (sGpsGeofencingInterface != NULL) { sGpsGeofencingInterface->pause_geofence(geofence_id); @@ -892,7 +939,7 @@ static jboolean android_location_GpsLocationProvider_pause_geofence(JNIEnv* /* e return JNI_FALSE; } -static jboolean android_location_GpsLocationProvider_resume_geofence(JNIEnv* /* env */, +static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */, jobject /* obj */, jint geofence_id, jint monitor_transition) { if (sGpsGeofencingInterface != NULL) { sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition); @@ -1272,7 +1319,7 @@ GpsMeasurementCallbacks sGpsMeasurementCallbacks = { measurement_callback, }; -static jboolean android_location_GpsLocationProvider_is_measurement_supported( +static jboolean android_location_GnssLocationProvider_is_measurement_supported( JNIEnv* env, jclass clazz) { if (sGpsMeasurementInterface != NULL) { @@ -1281,7 +1328,7 @@ static jboolean android_location_GpsLocationProvider_is_measurement_supported( return JNI_FALSE; } -static jboolean android_location_GpsLocationProvider_start_measurement_collection( +static jboolean android_location_GnssLocationProvider_start_measurement_collection( JNIEnv* env, jobject obj) { if (sGpsMeasurementInterface == NULL) { @@ -1298,7 +1345,7 @@ static jboolean android_location_GpsLocationProvider_start_measurement_collectio return JNI_TRUE; } -static jboolean android_location_GpsLocationProvider_stop_measurement_collection( +static jboolean android_location_GnssLocationProvider_stop_measurement_collection( JNIEnv* env, jobject obj) { if (sGpsMeasurementInterface == NULL) { @@ -1382,7 +1429,7 @@ GpsNavigationMessageCallbacks sGpsNavigationMessageCallbacks = { navigation_message_callback, }; -static jboolean android_location_GpsLocationProvider_is_navigation_message_supported( +static jboolean android_location_GnssLocationProvider_is_navigation_message_supported( JNIEnv* env, jclass clazz) { if(sGpsNavigationMessageInterface != NULL) { @@ -1391,7 +1438,7 @@ static jboolean android_location_GpsLocationProvider_is_navigation_message_suppo return JNI_FALSE; } -static jboolean android_location_GpsLocationProvider_start_navigation_message_collection( +static jboolean android_location_GnssLocationProvider_start_navigation_message_collection( JNIEnv* env, jobject obj) { if (sGpsNavigationMessageInterface == NULL) { @@ -1408,7 +1455,7 @@ static jboolean android_location_GpsLocationProvider_start_navigation_message_co return JNI_TRUE; } -static jboolean android_location_GpsLocationProvider_stop_navigation_message_collection( +static jboolean android_location_GnssLocationProvider_stop_navigation_message_collection( JNIEnv* env, jobject obj) { if (sGpsNavigationMessageInterface == NULL) { @@ -1420,7 +1467,7 @@ static jboolean android_location_GpsLocationProvider_stop_navigation_message_col return JNI_TRUE; } -static void android_location_GpsLocationProvider_configuration_update(JNIEnv* env, jobject obj, +static void android_location_GnssLocationProvider_configuration_update(JNIEnv* env, jobject obj, jstring config_content) { if (!sGnssConfigurationInterface) { @@ -1436,105 +1483,105 @@ static void android_location_GpsLocationProvider_configuration_update(JNIEnv* en static const JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ - {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native}, - {"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported}, + {"class_init_native", "()V", (void *)android_location_GnssLocationProvider_class_init_native}, + {"native_is_supported", "()Z", (void*)android_location_GnssLocationProvider_is_supported}, {"native_is_agps_ril_supported", "()Z", - (void*)android_location_GpsLocationProvider_is_agps_ril_supported}, + (void*)android_location_GnssLocationProvider_is_agps_ril_supported}, {"native_is_gnss_configuration_supported", "()Z", (void*)android_location_gpsLocationProvider_is_gnss_configuration_supported}, - {"native_init", "()Z", (void*)android_location_GpsLocationProvider_init}, - {"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup}, + {"native_init", "()Z", (void*)android_location_GnssLocationProvider_init}, + {"native_cleanup", "()V", (void*)android_location_GnssLocationProvider_cleanup}, {"native_set_position_mode", "(IIIII)Z", - (void*)android_location_GpsLocationProvider_set_position_mode}, - {"native_start", "()Z", (void*)android_location_GpsLocationProvider_start}, - {"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop}, + (void*)android_location_GnssLocationProvider_set_position_mode}, + {"native_start", "()Z", (void*)android_location_GnssLocationProvider_start}, + {"native_stop", "()Z", (void*)android_location_GnssLocationProvider_stop}, {"native_delete_aiding_data", "(I)V", - (void*)android_location_GpsLocationProvider_delete_aiding_data}, + (void*)android_location_GnssLocationProvider_delete_aiding_data}, {"native_read_sv_status", "([I[F[F[F[I)I", - (void*)android_location_GpsLocationProvider_read_sv_status}, - {"native_read_nmea", "([BI)I", (void*)android_location_GpsLocationProvider_read_nmea}, - {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time}, + (void*)android_location_GnssLocationProvider_read_sv_status}, + {"native_read_nmea", "([BI)I", (void*)android_location_GnssLocationProvider_read_nmea}, + {"native_inject_time", "(JJI)V", (void*)android_location_GnssLocationProvider_inject_time}, {"native_inject_location", "(DDF)V", - (void*)android_location_GpsLocationProvider_inject_location}, - {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra}, + (void*)android_location_GnssLocationProvider_inject_location}, + {"native_supports_xtra", "()Z", (void*)android_location_GnssLocationProvider_supports_xtra}, {"native_inject_xtra_data", "([BI)V", - (void*)android_location_GpsLocationProvider_inject_xtra_data}, + (void*)android_location_GnssLocationProvider_inject_xtra_data}, {"native_agps_data_conn_open", "(Ljava/lang/String;I)V", - (void*)android_location_GpsLocationProvider_agps_data_conn_open}, + (void*)android_location_GnssLocationProvider_agps_data_conn_open}, {"native_agps_data_conn_closed", "()V", - (void*)android_location_GpsLocationProvider_agps_data_conn_closed}, + (void*)android_location_GnssLocationProvider_agps_data_conn_closed}, {"native_agps_data_conn_failed", "()V", - (void*)android_location_GpsLocationProvider_agps_data_conn_failed}, + (void*)android_location_GnssLocationProvider_agps_data_conn_failed}, {"native_agps_set_id", "(ILjava/lang/String;)V", - (void*)android_location_GpsLocationProvider_agps_set_id}, + (void*)android_location_GnssLocationProvider_agps_set_id}, {"native_agps_set_ref_location_cellid", "(IIIII)V", - (void*)android_location_GpsLocationProvider_agps_set_reference_location_cellid}, + (void*)android_location_GnssLocationProvider_agps_set_reference_location_cellid}, {"native_set_agps_server", "(ILjava/lang/String;I)V", - (void*)android_location_GpsLocationProvider_set_agps_server}, + (void*)android_location_GnssLocationProvider_set_agps_server}, {"native_send_ni_response", "(II)V", - (void*)android_location_GpsLocationProvider_send_ni_response}, + (void*)android_location_GnssLocationProvider_send_ni_response}, {"native_agps_ni_message", "([BI)V", - (void *)android_location_GpsLocationProvider_agps_send_ni_message}, + (void *)android_location_GnssLocationProvider_agps_send_ni_message}, {"native_get_internal_state", "()Ljava/lang/String;", - (void*)android_location_GpsLocationProvider_get_internal_state}, + (void*)android_location_GnssLocationProvider_get_internal_state}, {"native_update_network_state", "(ZIZZLjava/lang/String;Ljava/lang/String;)V", - (void*)android_location_GpsLocationProvider_update_network_state }, + (void*)android_location_GnssLocationProvider_update_network_state }, {"native_is_geofence_supported", "()Z", - (void*) android_location_GpsLocationProvider_is_geofence_supported}, + (void*) android_location_GnssLocationProvider_is_geofence_supported}, {"native_add_geofence", "(IDDDIIII)Z", - (void *)android_location_GpsLocationProvider_add_geofence}, + (void *)android_location_GnssLocationProvider_add_geofence}, {"native_remove_geofence", "(I)Z", - (void *)android_location_GpsLocationProvider_remove_geofence}, - {"native_pause_geofence", "(I)Z", (void *)android_location_GpsLocationProvider_pause_geofence}, + (void *)android_location_GnssLocationProvider_remove_geofence}, + {"native_pause_geofence", "(I)Z", (void *)android_location_GnssLocationProvider_pause_geofence}, {"native_resume_geofence", "(II)Z", - (void *)android_location_GpsLocationProvider_resume_geofence}, + (void *)android_location_GnssLocationProvider_resume_geofence}, {"native_is_measurement_supported", "()Z", - (void*) android_location_GpsLocationProvider_is_measurement_supported}, + (void*) android_location_GnssLocationProvider_is_measurement_supported}, {"native_start_measurement_collection", "()Z", - (void*) android_location_GpsLocationProvider_start_measurement_collection}, + (void*) android_location_GnssLocationProvider_start_measurement_collection}, {"native_stop_measurement_collection", "()Z", - (void*) android_location_GpsLocationProvider_stop_measurement_collection}, + (void*) android_location_GnssLocationProvider_stop_measurement_collection}, {"native_is_navigation_message_supported", "()Z", - (void*) android_location_GpsLocationProvider_is_navigation_message_supported}, + (void*) android_location_GnssLocationProvider_is_navigation_message_supported}, {"native_start_navigation_message_collection", "()Z", - (void*) android_location_GpsLocationProvider_start_navigation_message_collection}, + (void*) android_location_GnssLocationProvider_start_navigation_message_collection}, {"native_stop_navigation_message_collection", "()Z", - (void*) android_location_GpsLocationProvider_stop_navigation_message_collection}, + (void*) android_location_GnssLocationProvider_stop_navigation_message_collection}, {"native_configuration_update", "(Ljava/lang/String;)V", - (void*)android_location_GpsLocationProvider_configuration_update}, + (void*)android_location_GnssLocationProvider_configuration_update}, }; -int register_android_server_location_GpsLocationProvider(JNIEnv* env) +int register_android_server_location_GnssLocationProvider(JNIEnv* env) { return jniRegisterNativeMethods( env, - "com/android/server/location/GpsLocationProvider", + "com/android/server/location/GnssLocationProvider", sMethods, NELEM(sMethods)); } diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index 1f3fde63e335f..a7010bcba5dd8 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -36,7 +36,7 @@ int register_android_server_UsbDeviceManager(JNIEnv* env); int register_android_server_UsbMidiDevice(JNIEnv* env); int register_android_server_UsbHostManager(JNIEnv* env); int register_android_server_VibratorService(JNIEnv* env); -int register_android_server_location_GpsLocationProvider(JNIEnv* env); +int register_android_server_location_GnssLocationProvider(JNIEnv* env); int register_android_server_location_FlpHardwareProvider(JNIEnv* env); int register_android_server_connectivity_Vpn(JNIEnv* env); int register_android_server_hdmi_HdmiCecController(JNIEnv* env); @@ -71,7 +71,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_UsbHostManager(env); register_android_server_VibratorService(env); register_android_server_SystemServer(env); - register_android_server_location_GpsLocationProvider(env); + register_android_server_location_GnssLocationProvider(env); register_android_server_location_FlpHardwareProvider(env); register_android_server_connectivity_Vpn(env); register_android_server_AssetAtlasService(env);