From d71cf1499b4def9ccb27a5224ba752a8dbba0e98 Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Fri, 21 Dec 2018 14:59:36 -0800 Subject: Add emergency session extension duration (framework) Add new method in IGnssConfiguration.hal to pass emergency session extension duration to GNSS HAL implemenation so that network initiated emergency location requests can be served for this extra duration post emergency call. Bug: 121204694 Test: GNSS HAL implementation not ready. So, tested with code instrumentation that this configuration parameter is called only for GNSS HAL 2.0 implementation. Change-Id: I845cc13412d9027b7924bfcffecbf6438f2e4be7 --- .../internal/location/GpsNetInitiatedHandler.java | 29 +- .../android/server/location/GnssConfiguration.java | 365 +++++++++++++++++++++ .../server/location/GnssLocationProvider.java | 226 ++----------- ...ndroid_server_location_GnssLocationProvider.cpp | 184 ++++++++--- 4 files changed, 533 insertions(+), 271 deletions(-) create mode 100644 services/core/java/com/android/server/location/GnssConfiguration.java diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java index b5313256e4dc..866634e17513 100644 --- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java +++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java @@ -16,9 +16,6 @@ package com.android.internal.location; -import java.io.UnsupportedEncodingException; -import java.util.concurrent.TimeUnit; - import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -26,20 +23,23 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.location.LocationManager; import android.location.INetInitiatedListener; +import android.location.LocationManager; +import android.os.RemoteException; import android.os.SystemClock; -import android.telephony.TelephonyManager; +import android.os.UserHandle; import android.telephony.PhoneNumberUtils; import android.telephony.PhoneStateListener; -import android.os.RemoteException; -import android.os.UserHandle; +import android.telephony.TelephonyManager; import android.util.Log; -import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.R; +import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.telephony.GsmAlphabet; +import java.io.UnsupportedEncodingException; +import java.util.concurrent.TimeUnit; + /** * A GPS Network-initiated Handler class used by LocationManager. * @@ -92,9 +92,6 @@ public class GpsNetInitiatedHandler { public static final int GPS_ENC_SUPL_UCS2 = 3; public static final int GPS_ENC_UNKNOWN = -1; - // Limit on SUPL NI emergency mode time extension after emergency sessions ends - private static final int MAX_EMERGENCY_MODE_EXTENSION_SECONDS = 300; // 5 minute maximum - private final Context mContext; private final TelephonyManager mTelephonyManager; private final PhoneStateListener mPhoneStateListener; @@ -252,19 +249,9 @@ public class GpsNetInitiatedHandler { } public void setEmergencyExtensionSeconds(int emergencyExtensionSeconds) { - if (emergencyExtensionSeconds > MAX_EMERGENCY_MODE_EXTENSION_SECONDS) { - Log.w(TAG, "emergencyExtensionSeconds " + emergencyExtensionSeconds - + " too high, reset to " + MAX_EMERGENCY_MODE_EXTENSION_SECONDS); - emergencyExtensionSeconds = MAX_EMERGENCY_MODE_EXTENSION_SECONDS; - } else if (emergencyExtensionSeconds < 0) { - Log.w(TAG, "emergencyExtensionSeconds " + emergencyExtensionSeconds - + " is negative, reset to zero."); - emergencyExtensionSeconds = 0; - } mEmergencyExtensionMillis = TimeUnit.SECONDS.toMillis(emergencyExtensionSeconds); } - // Handles NI events from HAL public void handleNiNotification(GpsNiNotification notif) { if (DEBUG) Log.d(TAG, "in handleNiNotification () :" diff --git a/services/core/java/com/android/server/location/GnssConfiguration.java b/services/core/java/com/android/server/location/GnssConfiguration.java new file mode 100644 index 000000000000..29465ad366f4 --- /dev/null +++ b/services/core/java/com/android/server/location/GnssConfiguration.java @@ -0,0 +1,365 @@ +/* + * Copyright (C) 2019 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 com.android.server.location; + +import android.content.Context; +import android.os.PersistableBundle; +import android.os.SystemProperties; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; +import android.text.TextUtils; +import android.util.Log; + +import libcore.io.IoUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; + +/** + * A utility class to hold GNSS configuration properties. + * + * The trigger to load/reload the configuration parameters should be managed by the class + * that owns an instance of this class. + * + * Instances of this class are not thread-safe and should either be used from a single thread + * or with external synchronization when used by multiple threads. + */ +class GnssConfiguration { + private static final String TAG = "GnssConfiguration"; + + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + //TODO(b/33112647): Create gps_debug.conf with commented career parameters. + private static final String DEBUG_PROPERTIES_FILE = "/etc/gps_debug.conf"; + + // config.xml properties + private static final String CONFIG_SUPL_HOST = "SUPL_HOST"; + private static final String CONFIG_SUPL_PORT = "SUPL_PORT"; + private static final String CONFIG_C2K_HOST = "C2K_HOST"; + private static final String CONFIG_C2K_PORT = "C2K_PORT"; + private static final String CONFIG_SUPL_VER = "SUPL_VER"; + private static final String CONFIG_SUPL_MODE = "SUPL_MODE"; + private static final String CONFIG_SUPL_ES = "SUPL_ES"; + private static final String CONFIG_LPP_PROFILE = "LPP_PROFILE"; + private static final String CONFIG_A_GLONASS_POS_PROTOCOL_SELECT = + "A_GLONASS_POS_PROTOCOL_SELECT"; + private static final String CONFIG_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = + "USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL"; + private static final String CONFIG_GPS_LOCK = "GPS_LOCK"; + private static final String CONFIG_ES_EXTENSION_SEC = "ES_EXTENSION_SEC"; + + // Limit on NI emergency mode time extension after emergency sessions ends + private static final int MAX_EMERGENCY_MODE_EXTENSION_SECONDS = 300; // 5 minute maximum + + // Persist property for LPP_PROFILE + static final String LPP_PROFILE = "persist.sys.gps.lpp"; + + // Represents an HAL interface version. Instances of this class are created in the JNI layer + // and returned through native methods. + private static class HalInterfaceVersion { + final int mMajor; + final int mMinor; + + HalInterfaceVersion(int major, int minor) { + mMajor = major; + mMinor = minor; + } + } + + /** + * Properties loaded from PROPERTIES_FILE. + */ + private Properties mProperties; + + private int mEsExtensionSec = 0; + + private final Context mContext; + + GnssConfiguration(Context context) { + mContext = context; + mProperties = new Properties(); + } + + /** + * Returns the full set of properties loaded. + */ + Properties getProperties() { + return mProperties; + } + + /** + * Returns the value of config parameter ES_EXTENSION_SEC. The value is range checked + * and constrained to min/max limits. + */ + int getEsExtensionSec() { + return mEsExtensionSec; + } + + /** + * Returns the value of config parameter SUPL_HOST or {@code null} if no value is + * provided. + */ + String getSuplHost() { + return mProperties.getProperty(CONFIG_SUPL_HOST); + } + + /** + * Returns the value of config parameter SUPL_PORT or {@code defaultPort} if no value is + * provided or if there is an error parsing the configured value. + */ + int getSuplPort(int defaultPort) { + return getIntConfig(CONFIG_SUPL_PORT, defaultPort); + } + + /** + * Returns the value of config parameter C2K_HOST or {@code null} if no value is + * provided. + */ + String getC2KHost() { + return mProperties.getProperty(CONFIG_C2K_HOST); + } + + /** + * Returns the value of config parameter C2K_PORT or {@code defaultPort} if no value is + * provided or if there is an error parsing the configured value. + */ + int getC2KPort(int defaultPort) { + return getIntConfig(CONFIG_C2K_PORT, defaultPort); + } + + /** + * Returns the value of config parameter SUPL_MODE or {@code defaultMode} if no value is + * provided or if there is an error parsing the configured value. + */ + int getSuplMode(int defaultMode) { + return getIntConfig(CONFIG_SUPL_MODE, defaultMode); + } + + /** + * Returns the value of config parameter SUPL_ES or {@code defaultSuplEs} if no value is + * provided or if there is an error parsing the configured value. + */ + int getSuplEs(int defaulSuplEs) { + return getIntConfig(CONFIG_SUPL_ES, defaulSuplEs); + } + + /** + * Returns the value of config parameter LPP_PROFILE or {@code null} if no value is + * provided. + */ + String getLppProfile() { + return mProperties.getProperty(CONFIG_LPP_PROFILE); + } + + /** + * Updates the GNSS HAL satellite blacklist. + */ + void setSatelliteBlacklist(int[] constellations, int[] svids) { + native_set_satellite_blacklist(constellations, svids); + } + + interface SetCarrierProperty { + boolean set(int value); + } + + /** + * Loads the GNSS properties from carrier config file followed by the properties from + * gps debug config file. + */ + void reloadGpsProperties() { + if (DEBUG) Log.d(TAG, "Reset GPS properties, previous size = " + mProperties.size()); + loadPropertiesFromCarrierConfig(); + + String lpp_prof = SystemProperties.get(LPP_PROFILE); + if (!TextUtils.isEmpty(lpp_prof)) { + // override default value of this if lpp_prof is not empty + mProperties.setProperty(CONFIG_LPP_PROFILE, lpp_prof); + } + /* + * Overlay carrier properties from a debug configuration file. + */ + loadPropertiesFromGpsDebugConfig(mProperties); + + mEsExtensionSec = getRangeCheckedConfigEsExtensionSec(); + + final HalInterfaceVersion gnssConfigurationIfaceVersion = + native_get_gnss_configuration_version(); + if (gnssConfigurationIfaceVersion != null) { + // Set to a range checked value. + if (isConfigEsExtensionSecSupported(gnssConfigurationIfaceVersion) + && !native_set_es_extension_sec(mEsExtensionSec)) { + Log.e(TAG, "Unable to set " + CONFIG_ES_EXTENSION_SEC + ": " + mEsExtensionSec); + } + + Map map = new HashMap() { + { + put(CONFIG_SUPL_VER, GnssConfiguration::native_set_supl_version); + put(CONFIG_SUPL_MODE, GnssConfiguration::native_set_supl_mode); + + if (isConfigSuplEsSupported(gnssConfigurationIfaceVersion)) { + put(CONFIG_SUPL_ES, GnssConfiguration::native_set_supl_es); + } + + put(CONFIG_LPP_PROFILE, GnssConfiguration::native_set_lpp_profile); + put(CONFIG_A_GLONASS_POS_PROTOCOL_SELECT, + GnssConfiguration::native_set_gnss_pos_protocol_select); + put(CONFIG_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL, + GnssConfiguration::native_set_emergency_supl_pdn); + + if (isConfigGpsLockSupported(gnssConfigurationIfaceVersion)) { + put(CONFIG_GPS_LOCK, GnssConfiguration::native_set_gps_lock); + } + } + }; + + for (Entry entry : map.entrySet()) { + String propertyName = entry.getKey(); + String propertyValueString = mProperties.getProperty(propertyName); + if (propertyValueString != null) { + try { + int propertyValueInt = Integer.decode(propertyValueString); + boolean result = entry.getValue().set(propertyValueInt); + if (!result) { + Log.e(TAG, "Unable to set " + propertyName); + } + } catch (NumberFormatException e) { + Log.e(TAG, "Unable to parse propertyName: " + propertyValueString); + } + } + } + } else if (DEBUG) { + Log.d(TAG, "Skipped configuration update because GNSS configuration in GPS HAL is not" + + " supported"); + } + } + + /** + * Loads GNSS properties from carrier config file. + */ + void loadPropertiesFromCarrierConfig() { + CarrierConfigManager configManager = (CarrierConfigManager) + mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); + if (configManager == null) { + return; + } + PersistableBundle configs = configManager.getConfigForSubId( + SubscriptionManager.getDefaultDataSubscriptionId()); + if (configs == null) { + if (DEBUG) Log.d(TAG, "SIM not ready, use default carrier config."); + configs = CarrierConfigManager.getDefaultConfig(); + } + for (String configKey : configs.keySet()) { + if (configKey.startsWith(CarrierConfigManager.Gps.KEY_PREFIX)) { + String key = configKey + .substring(CarrierConfigManager.Gps.KEY_PREFIX.length()) + .toUpperCase(); + Object value = configs.get(configKey); + if (value instanceof String) { + // All GPS properties are of String type; convert so. + if (DEBUG) Log.d(TAG, "Gps config: " + key + " = " + value); + mProperties.setProperty(key, (String) value); + } + } + } + } + + private void loadPropertiesFromGpsDebugConfig(Properties properties) { + try { + File file = new File(DEBUG_PROPERTIES_FILE); + FileInputStream stream = null; + try { + stream = new FileInputStream(file); + properties.load(stream); + } finally { + IoUtils.closeQuietly(stream); + } + } catch (IOException e) { + if (DEBUG) Log.d(TAG, "Could not open GPS configuration file " + DEBUG_PROPERTIES_FILE); + } + } + + private int getRangeCheckedConfigEsExtensionSec() { + int emergencyExtensionSeconds = getIntConfig(CONFIG_ES_EXTENSION_SEC, 0); + if (emergencyExtensionSeconds > MAX_EMERGENCY_MODE_EXTENSION_SECONDS) { + Log.w(TAG, CONFIG_ES_EXTENSION_SEC + ": " + emergencyExtensionSeconds + + " too high, reset to " + MAX_EMERGENCY_MODE_EXTENSION_SECONDS); + emergencyExtensionSeconds = MAX_EMERGENCY_MODE_EXTENSION_SECONDS; + } else if (emergencyExtensionSeconds < 0) { + Log.w(TAG, CONFIG_ES_EXTENSION_SEC + ": " + emergencyExtensionSeconds + + " is negative, reset to zero."); + emergencyExtensionSeconds = 0; + } + return emergencyExtensionSeconds; + } + + private int getIntConfig(String configParameter, int defaultValue) { + String valueString = mProperties.getProperty(configParameter); + if (TextUtils.isEmpty(valueString)) { + return defaultValue; + } + try { + return Integer.parseInt(valueString); + } catch (NumberFormatException e) { + Log.e(TAG, "Unable to parse config parameter " + configParameter + " value: " + + valueString + ". Using default value: " + defaultValue); + return defaultValue; + } + } + + private static boolean isConfigEsExtensionSecSupported( + HalInterfaceVersion gnssConfiguartionIfaceVersion) { + // ES_EXTENSION_SEC is introduced in @2.0::IGnssConfiguration.hal + return gnssConfiguartionIfaceVersion.mMajor >= 2; + } + + private static boolean isConfigSuplEsSupported( + HalInterfaceVersion gnssConfiguartionIfaceVersion) { + // SUPL_ES is deprecated in @2.0::IGnssConfiguration.hal + return gnssConfiguartionIfaceVersion.mMajor < 2; + } + + private static boolean isConfigGpsLockSupported( + HalInterfaceVersion gnssConfiguartionIfaceVersion) { + // GPS_LOCK is deprecated in @2.0::IGnssConfiguration.hal + return gnssConfiguartionIfaceVersion.mMajor < 2; + } + + private static native HalInterfaceVersion native_get_gnss_configuration_version(); + + private static native boolean native_set_supl_version(int version); + + private static native boolean native_set_supl_mode(int mode); + + private static native boolean native_set_supl_es(int es); + + private static native boolean native_set_lpp_profile(int lppProfile); + + private static native boolean native_set_gnss_pos_protocol_select(int gnssPosProtocolSelect); + + private static native boolean native_set_gps_lock(int gpsLock); + + private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn); + + private static native boolean native_set_satellite_blacklist(int[] constellations, int[] svIds); + + private static native boolean native_set_es_extension_sec(int emergencyExtensionSeconds); +} diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index 05d77ab5867e..3c81a4569407 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -74,12 +74,7 @@ import com.android.internal.location.gnssmetrics.GnssMetrics; import com.android.server.location.GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback; import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback; -import libcore.io.IoUtils; - -import java.io.File; import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.IOException; import java.io.PrintWriter; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -87,11 +82,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; /** * A GNSS implementation of LocationProvider used by LocationManager. @@ -147,7 +138,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private static final int LOCATION_HAS_SPEED_ACCURACY = 64; private static final int LOCATION_HAS_BEARING_ACCURACY = 128; - // IMPORTANT - the GPS_DELETE_* symbols here must match GnssAidingData enum in IGnss.hal private static final int GPS_DELETE_EPHEMERIS = 0x0001; private static final int GPS_DELETE_ALMANAC = 0x0002; @@ -200,9 +190,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1; private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2; - //TODO(b/33112647): Create gps_debug.conf with commented career parameters. - private static final String DEBUG_PROPERTIES_FILE = "/etc/gps_debug.conf"; - // ref. location info private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1; private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2; @@ -375,7 +362,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements * Properties loaded from PROPERTIES_FILE. * It must be accessed only inside {@link #mHandler}. */ - private Properties mProperties; + private GnssConfiguration mGnssConfiguration; private String mSuplServerHost; private int mSuplServerPort = TCP_MIN_PORT; @@ -411,10 +398,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP"; private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT"; - // Persist property for LPP_PROFILE - private final static String LPP_PROFILE = "persist.sys.gps.lpp"; - - private final PowerManager mPowerManager; private final AlarmManager mAlarmManager; private final PendingIntent mWakeupIntent; @@ -502,7 +485,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements */ @Override public void onUpdateSatelliteBlacklist(int[] constellations, int[] svids) { - mHandler.post(() -> native_set_satellite_blacklist(constellations, svids)); + mHandler.post(() -> mGnssConfiguration.setSatelliteBlacklist(constellations, svids)); } private void subscriptionOrCarrierConfigChanged(Context context) { @@ -525,17 +508,17 @@ public class GnssLocationProvider extends AbstractLocationProvider implements } if (isKeepLppProfile) { // load current properties for the carrier - loadPropertiesFromCarrierConfig(context, mProperties); - String lpp_profile = mProperties.getProperty("LPP_PROFILE"); + mGnssConfiguration.loadPropertiesFromCarrierConfig(); + String lpp_profile = mGnssConfiguration.getLppProfile(); // set the persist property LPP_PROFILE for the value if (lpp_profile != null) { - SystemProperties.set(LPP_PROFILE, lpp_profile); + SystemProperties.set(GnssConfiguration.LPP_PROFILE, lpp_profile); } } else { // reset the persist property - SystemProperties.set(LPP_PROFILE, ""); + SystemProperties.set(GnssConfiguration.LPP_PROFILE, ""); } - reloadGpsProperties(context, mProperties); + reloadGpsProperties(); mNIHandler.setSuplEsEnabled(mSuplEsEnabled); } } else { @@ -564,133 +547,14 @@ public class GnssLocationProvider extends AbstractLocationProvider implements return native_is_supported(); } - interface SetCarrierProperty { - boolean set(int value); - } - - private void reloadGpsProperties(Context context, Properties properties) { - if (DEBUG) Log.d(TAG, "Reset GPS properties, previous size = " + properties.size()); - loadPropertiesFromCarrierConfig(context, properties); - - String lpp_prof = SystemProperties.get(LPP_PROFILE); - if (!TextUtils.isEmpty(lpp_prof)) { - // override default value of this if lpp_prof is not empty - properties.setProperty("LPP_PROFILE", lpp_prof); - } - /* - * Overlay carrier properties from a debug configuration file. - */ - loadPropertiesFromGpsDebugConfig(properties); + private void reloadGpsProperties() { + mGnssConfiguration.reloadGpsProperties(); + setSuplHostPort(); // TODO: we should get rid of C2K specific setting. - setSuplHostPort(properties.getProperty("SUPL_HOST"), - properties.getProperty("SUPL_PORT")); - mC2KServerHost = properties.getProperty("C2K_HOST"); - String portString = properties.getProperty("C2K_PORT"); - if (mC2KServerHost != null && portString != null) { - try { - mC2KServerPort = Integer.parseInt(portString); - } catch (NumberFormatException e) { - Log.e(TAG, "unable to parse C2K_PORT: " + portString); - } - } - if (native_is_gnss_configuration_supported()) { - Map map = new HashMap() { - { - put("SUPL_VER", GnssLocationProvider::native_set_supl_version); - put("SUPL_MODE", GnssLocationProvider::native_set_supl_mode); - put("SUPL_ES", GnssLocationProvider::native_set_supl_es); - put("LPP_PROFILE", GnssLocationProvider::native_set_lpp_profile); - put("A_GLONASS_POS_PROTOCOL_SELECT", - GnssLocationProvider::native_set_gnss_pos_protocol_select); - put("USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL", - GnssLocationProvider::native_set_emergency_supl_pdn); - put("GPS_LOCK", GnssLocationProvider::native_set_gps_lock); - } - }; - - for (Entry entry : map.entrySet()) { - String propertyName = entry.getKey(); - String propertyValueString = properties.getProperty(propertyName); - if (propertyValueString != null) { - try { - int propertyValueInt = Integer.decode(propertyValueString); - boolean result = entry.getValue().set(propertyValueInt); - if (!result) { - Log.e(TAG, "Unable to set " + propertyName); - } - } catch (NumberFormatException e) { - Log.e(TAG, "unable to parse propertyName: " + propertyValueString); - } - } - } - } else if (DEBUG) { - Log.d(TAG, "Skipped configuration update because GNSS configuration in GPS HAL is not" - + " supported"); - } - - // SUPL_ES configuration. - String suplESProperty = mProperties.getProperty("SUPL_ES"); - if (suplESProperty != null) { - try { - mSuplEsEnabled = (Integer.parseInt(suplESProperty) == 1); - } catch (NumberFormatException e) { - Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty); - } - } - - String emergencyExtensionSecondsString - = properties.getProperty("ES_EXTENSION_SEC", "0"); - try { - int emergencyExtensionSeconds = - Integer.parseInt(emergencyExtensionSecondsString); - mNIHandler.setEmergencyExtensionSeconds(emergencyExtensionSeconds); - } catch (NumberFormatException e) { - Log.e(TAG, "unable to parse ES_EXTENSION_SEC: " - + emergencyExtensionSecondsString); - } - } - - private void loadPropertiesFromCarrierConfig(Context context, Properties properties) { - CarrierConfigManager configManager = (CarrierConfigManager) - mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); - if (configManager == null) { - return; - } - PersistableBundle configs = configManager.getConfigForSubId( - SubscriptionManager.getDefaultDataSubscriptionId()); - if (configs == null) { - if (DEBUG) Log.d(TAG, "SIM not ready, use default carrier config."); - configs = CarrierConfigManager.getDefaultConfig(); - } - for (String configKey : configs.keySet()) { - if (configKey.startsWith(CarrierConfigManager.Gps.KEY_PREFIX)) { - String key = configKey - .substring(CarrierConfigManager.Gps.KEY_PREFIX.length()) - .toUpperCase(); - Object value = configs.get(configKey); - if (value instanceof String) { - // All GPS properties are of String type; convert so. - if (DEBUG) Log.d(TAG, "Gps config: " + key + " = " + value); - properties.setProperty(key, (String) value); - } - } - } - } - - private void loadPropertiesFromGpsDebugConfig(Properties properties) { - try { - File file = new File(DEBUG_PROPERTIES_FILE); - FileInputStream stream = null; - try { - stream = new FileInputStream(file); - properties.load(stream); - } finally { - IoUtils.closeQuietly(stream); - } - - } catch (IOException e) { - if (DEBUG) Log.d(TAG, "Could not open GPS configuration file " + DEBUG_PROPERTIES_FILE); - } + mC2KServerHost = mGnssConfiguration.getC2KHost(); + mC2KServerPort = mGnssConfiguration.getC2KPort(TCP_MIN_PORT); + mNIHandler.setEmergencyExtensionSeconds(mGnssConfiguration.getEsExtensionSec()); + mSuplEsEnabled = mGnssConfiguration.getSuplEs(0) == 1; } public GnssLocationProvider(Context context, LocationProviderManager locationProviderManager, @@ -733,7 +597,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements // relative long time, so the ctor() is kept to create objects needed by this instance, // while IO initialization and registration is delegated to our internal handler // this approach is just fine because events are posted to our handler anyway - mProperties = new Properties(); + mGnssConfiguration = new GnssConfiguration(mContext); sendMessage(INITIALIZE_HANDLER, 0, null); // Create a GPS net-initiated handler. @@ -918,7 +782,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mDownloadXtraWakeLock.acquire(DOWNLOAD_XTRA_DATA_TIMEOUT_MS); Log.i(TAG, "WakeLock acquired by handleDownloadXtraData()"); AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { - GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mProperties); + GpsXtraDownloader xtraDownloader = new GpsXtraDownloader( + mGnssConfiguration.getProperties()); byte[] data = xtraDownloader.downloadXtraData(); if (data != null) { if (DEBUG) Log.d(TAG, "calling native_inject_xtra_data"); @@ -963,17 +828,9 @@ public class GnssLocationProvider extends AbstractLocationProvider implements } } - private void setSuplHostPort(String hostString, String portString) { - if (hostString != null) { - mSuplServerHost = hostString; - } - if (portString != null) { - try { - mSuplServerPort = Integer.parseInt(portString); - } catch (NumberFormatException e) { - Log.e(TAG, "unable to parse SUPL_PORT: " + portString); - } - } + private void setSuplHostPort() { + mSuplServerHost = mGnssConfiguration.getSuplHost(); + mSuplServerPort = mGnssConfiguration.getSuplPort(TCP_MIN_PORT); if (mSuplServerHost != null && mSuplServerPort > TCP_MIN_PORT && mSuplServerPort <= TCP_MAX_PORT) { @@ -986,23 +843,17 @@ public class GnssLocationProvider extends AbstractLocationProvider implements * Checks what SUPL mode to use, according to the AGPS mode as well as the * allowed mode from properties. * - * @param properties GPS properties * @param agpsEnabled whether AGPS is enabled by settings value * @param singleShot whether "singleshot" is needed * @return SUPL mode (MSA vs MSB vs STANDALONE) */ - private int getSuplMode(Properties properties, boolean agpsEnabled, boolean singleShot) { + private int getSuplMode(boolean agpsEnabled, boolean singleShot) { if (agpsEnabled) { - String modeString = properties.getProperty("SUPL_MODE"); - int suplMode = 0; - if (!TextUtils.isEmpty(modeString)) { - try { - suplMode = Integer.parseInt(modeString); - } catch (NumberFormatException e) { - Log.e(TAG, "unable to parse SUPL_MODE: " + modeString); - return GPS_POSITION_MODE_STANDALONE; - } + int suplMode = mGnssConfiguration.getSuplMode(0); + if (suplMode == 0) { + return GPS_POSITION_MODE_STANDALONE; } + // MS-Based is the preferred mode for Assisted-GPS position computation, so we favor // such mode when it is available if (hasCapability(GPS_CAPABILITY_MSB) && (suplMode & AGPS_SUPL_MODE_MSB) != 0) { @@ -1307,7 +1158,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements boolean agpsEnabled = (Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0); - mPositionMode = getSuplMode(mProperties, agpsEnabled, singleShot); + mPositionMode = getSuplMode(agpsEnabled, singleShot); if (DEBUG) { String mode; @@ -1670,7 +1521,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements // re-calls native_init() and other setup. handleEnable(); // resend configuration into the restarted HAL service. - reloadGpsProperties(mContext, mProperties); + reloadGpsProperties(); } }); } @@ -2072,7 +1923,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements // load default GPS configuration // (this configuration might change in the future based on SIM changes) - reloadGpsProperties(mContext, mProperties); + reloadGpsProperties(); // TODO: When this object "finishes" we should unregister by invoking // SubscriptionManager.getInstance(mContext).unregister @@ -2227,8 +2078,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private static native boolean native_is_supported(); - private static native boolean native_is_gnss_configuration_supported(); - private static native void native_init_once(); private native boolean native_init(); @@ -2284,21 +2133,4 @@ public class GnssLocationProvider extends AbstractLocationProvider implements int lac, int cid); private native void native_agps_set_id(int type, String setid); - - // GNSS Configuration - private static native boolean native_set_supl_version(int version); - - private static native boolean native_set_supl_mode(int mode); - - private static native boolean native_set_supl_es(int es); - - private static native boolean native_set_lpp_profile(int lppProfile); - - private static native boolean native_set_gnss_pos_protocol_select(int gnssPosProtocolSelect); - - private static native boolean native_set_gps_lock(int gpsLock); - - private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn); - - private static native boolean native_set_satellite_blacklist(int[] constellations, int[] svIds); -} +} \ No newline at end of file diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index 6d8fc1c88307..b290bc516320 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -135,6 +135,7 @@ using IGnss_V1_1 = android::hardware::gnss::V1_1::IGnss; using IGnss_V2_0 = android::hardware::gnss::V2_0::IGnss; using IGnssConfiguration_V1_0 = android::hardware::gnss::V1_0::IGnssConfiguration; using IGnssConfiguration_V1_1 = android::hardware::gnss::V1_1::IGnssConfiguration; +using IGnssConfiguration_V2_0 = android::hardware::gnss::V2_0::IGnssConfiguration; using IGnssMeasurement_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurement; using IGnssMeasurement_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurement; using IGnssMeasurement_V2_0 = android::hardware::gnss::V2_0::IGnssMeasurement; @@ -179,6 +180,7 @@ sp gnssBatchingIface = nullptr; sp gnssDebugIface = nullptr; sp gnssConfigurationIface = nullptr; sp gnssConfigurationIface_V1_1 = nullptr; +sp gnssConfigurationIface_V2_0 = nullptr; sp gnssNiIface = nullptr; sp gnssMeasurementIface = nullptr; sp gnssMeasurementIface_V1_1 = nullptr; @@ -313,6 +315,15 @@ static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodNa } } +static jobject createHalInterfaceVersionJavaObject(JNIEnv* env, jint major, jint minor) { + jclass versionClass = + env->FindClass("com/android/server/location/GnssConfiguration$HalInterfaceVersion"); + jmethodID versionCtor = env->GetMethodID(versionClass, "", "(II)V"); + jobject version = env->NewObject(versionClass, versionCtor, major, minor); + env->DeleteLocalRef(versionClass); + return version; +} + struct ScopedJniString { ScopedJniString(JNIEnv* env, jstring javaString) : mEnv(env), mJavaString(javaString) { mNativeString = mEnv->GetStringUTFChars(mJavaString, nullptr); @@ -1421,10 +1432,19 @@ static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass gnssNiIface = gnssNi; } - if (gnssHal_V1_1 != nullptr) { + if (gnssHal_V2_0 != nullptr) { + auto gnssConfiguration = gnssHal_V2_0->getExtensionGnssConfiguration_2_0(); + if (!gnssConfiguration.isOk()) { + ALOGD("Unable to get a handle to GnssConfiguration_V2_0"); + } else { + gnssConfigurationIface_V2_0 = gnssConfiguration; + gnssConfigurationIface_V1_1 = gnssConfigurationIface_V2_0; + gnssConfigurationIface = gnssConfigurationIface_V2_0; + } + } else if (gnssHal_V1_1 != nullptr) { auto gnssConfiguration = gnssHal_V1_1->getExtensionGnssConfiguration_1_1(); if (!gnssConfiguration.isOk()) { - ALOGD("Unable to get a handle to GnssConfiguration"); + ALOGD("Unable to get a handle to GnssConfiguration_V1_1"); } else { gnssConfigurationIface_V1_1 = gnssConfiguration; gnssConfigurationIface = gnssConfigurationIface_V1_1; @@ -1463,9 +1483,23 @@ static jboolean android_location_GnssNetworkConnectivityHandler_is_agps_ril_supp return (agnssRilIface != nullptr) ? JNI_TRUE : JNI_FALSE; } -static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported( - JNIEnv* /* env */, jclass /* jclazz */) { - return (gnssConfigurationIface != nullptr) ? JNI_TRUE : JNI_FALSE; +static jobject android_location_GnssConfiguration_get_gnss_configuration_version( + JNIEnv* env, jclass /* jclazz */) { + jint major, minor; + if (gnssConfigurationIface_V2_0 != nullptr) { + major = 2; + minor = 0; + } else if (gnssConfigurationIface_V1_1 != nullptr) { + major = 1; + minor = 1; + } else if (gnssConfigurationIface != nullptr) { + major = 1; + minor = 0; + } else { + return nullptr; + } + + return createHalInterfaceVersionJavaObject(env, major, minor); } static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj) { @@ -2278,9 +2312,9 @@ static jboolean android_location_GnssNavigationMessageProvider_stop_navigation_m return boolToJbool(result.isOk()); } -static jboolean android_location_GnssLocationProvider_set_emergency_supl_pdn(JNIEnv*, - jobject, - jint emergencySuplPdn) { +static jboolean android_location_GnssConfiguration_set_emergency_supl_pdn(JNIEnv*, + jobject, + jint emergencySuplPdn) { if (gnssConfigurationIface == nullptr) { ALOGE("no GNSS configuration interface available"); return JNI_FALSE; @@ -2294,7 +2328,7 @@ static jboolean android_location_GnssLocationProvider_set_emergency_supl_pdn(JNI } } -static jboolean android_location_GnssLocationProvider_set_supl_version(JNIEnv*, +static jboolean android_location_GnssConfiguration_set_supl_version(JNIEnv*, jobject, jint version) { if (gnssConfigurationIface == nullptr) { @@ -2309,9 +2343,14 @@ static jboolean android_location_GnssLocationProvider_set_supl_version(JNIEnv*, } } -static jboolean android_location_GnssLocationProvider_set_supl_es(JNIEnv*, - jobject, - jint suplEs) { +static jboolean android_location_GnssConfiguration_set_supl_es(JNIEnv*, + jobject, + jint suplEs) { + if (gnssConfigurationIface_V2_0 != nullptr) { + ALOGI("Config parameter SUPL_ES is deprecated in IGnssConfiguration.hal version 2.0."); + return JNI_FALSE; + } + if (gnssConfigurationIface == nullptr) { ALOGE("no GNSS configuration interface available"); return JNI_FALSE; @@ -2325,9 +2364,9 @@ static jboolean android_location_GnssLocationProvider_set_supl_es(JNIEnv*, } } -static jboolean android_location_GnssLocationProvider_set_supl_mode(JNIEnv*, - jobject, - jint mode) { +static jboolean android_location_GnssConfiguration_set_supl_mode(JNIEnv*, + jobject, + jint mode) { if (gnssConfigurationIface == nullptr) { ALOGE("no GNSS configuration interface available"); return JNI_FALSE; @@ -2341,9 +2380,14 @@ static jboolean android_location_GnssLocationProvider_set_supl_mode(JNIEnv*, } } -static jboolean android_location_GnssLocationProvider_set_gps_lock(JNIEnv*, - jobject, - jint gpsLock) { +static jboolean android_location_GnssConfiguration_set_gps_lock(JNIEnv*, + jobject, + jint gpsLock) { + if (gnssConfigurationIface_V2_0 != nullptr) { + ALOGI("Config parameter GPS_LOCK is deprecated in IGnssConfiguration.hal version 2.0."); + return JNI_FALSE; + } + if (gnssConfigurationIface == nullptr) { ALOGE("no GNSS configuration interface available"); return JNI_FALSE; @@ -2357,7 +2401,7 @@ static jboolean android_location_GnssLocationProvider_set_gps_lock(JNIEnv*, } } -static jboolean android_location_GnssLocationProvider_set_lpp_profile(JNIEnv*, +static jboolean android_location_GnssConfiguration_set_lpp_profile(JNIEnv*, jobject, jint lppProfile) { if (gnssConfigurationIface == nullptr) { @@ -2374,9 +2418,9 @@ static jboolean android_location_GnssLocationProvider_set_lpp_profile(JNIEnv*, } } -static jboolean android_location_GnssLocationProvider_set_gnss_pos_protocol_select(JNIEnv*, - jobject, - jint gnssPosProtocol) { +static jboolean android_location_GnssConfiguration_set_gnss_pos_protocol_select(JNIEnv*, + jobject, + jint gnssPosProtocol) { if (gnssConfigurationIface == nullptr) { ALOGE("no GNSS configuration interface available"); return JNI_FALSE; @@ -2390,7 +2434,7 @@ static jboolean android_location_GnssLocationProvider_set_gnss_pos_protocol_sele } } -static jboolean android_location_GnssLocationProvider_set_satellite_blacklist( +static jboolean android_location_GnssConfiguration_set_satellite_blacklist( JNIEnv* env, jobject, jintArray constellations, jintArray sv_ids) { if (gnssConfigurationIface_V1_1 == nullptr) { ALOGI("No GNSS Satellite Blacklist interface available"); @@ -2431,6 +2475,27 @@ static jboolean android_location_GnssLocationProvider_set_satellite_blacklist( } } +static jboolean android_location_GnssConfiguration_set_es_extension_sec( + JNIEnv*, jobject, jint emergencyExtensionSeconds) { + if (gnssConfigurationIface == nullptr) { + ALOGE("no GNSS configuration interface available"); + return JNI_FALSE; + } + + if (gnssConfigurationIface_V2_0 == nullptr) { + ALOGI("Config parameter ES_EXTENSION_SEC is not supported in IGnssConfiguration.hal" + " versions earlier than 2.0."); + return JNI_FALSE; + } + + auto result = gnssConfigurationIface_V2_0->setEsExtensionSec(emergencyExtensionSeconds); + if (result.isOk()) { + return result; + } else { + return JNI_FALSE; + } +} + static jint android_location_GnssBatchingProvider_get_batch_size(JNIEnv*, jclass) { if (gnssBatchingIface == nullptr) { return 0; // batching not supported, size = 0 @@ -2498,17 +2563,14 @@ static const JNINativeMethod sMethods[] = { android_location_GnssLocationProvider_class_init_native)}, {"native_is_supported", "()Z", reinterpret_cast( android_location_GnssLocationProvider_is_supported)}, - {"native_is_gnss_configuration_supported", "()Z", - reinterpret_cast( - android_location_gpsLocationProvider_is_gnss_configuration_supported)}, {"native_init_once", "()V", reinterpret_cast( android_location_GnssLocationProvider_init_once)}, {"native_init", "()Z", reinterpret_cast(android_location_GnssLocationProvider_init)}, {"native_cleanup", "()V", reinterpret_cast( android_location_GnssLocationProvider_cleanup)}, {"native_set_position_mode", - "(IIIIIZ)Z", - reinterpret_cast(android_location_GnssLocationProvider_set_position_mode)}, + "(IIIIIZ)Z", + reinterpret_cast(android_location_GnssLocationProvider_set_position_mode)}, {"native_start", "()Z", reinterpret_cast(android_location_GnssLocationProvider_start)}, {"native_stop", "()Z", reinterpret_cast(android_location_GnssLocationProvider_stop)}, {"native_delete_aiding_data", @@ -2545,31 +2607,6 @@ static const JNINativeMethod sMethods[] = { {"native_get_internal_state", "()Ljava/lang/String;", reinterpret_cast(android_location_GnssLocationProvider_get_internal_state)}, - {"native_set_supl_es", - "(I)Z", - reinterpret_cast(android_location_GnssLocationProvider_set_supl_es)}, - {"native_set_supl_version", - "(I)Z", - reinterpret_cast(android_location_GnssLocationProvider_set_supl_version)}, - {"native_set_supl_mode", - "(I)Z", - reinterpret_cast(android_location_GnssLocationProvider_set_supl_mode)}, - {"native_set_lpp_profile", - "(I)Z", - reinterpret_cast(android_location_GnssLocationProvider_set_lpp_profile)}, - {"native_set_gnss_pos_protocol_select", - "(I)Z", - reinterpret_cast( - android_location_GnssLocationProvider_set_gnss_pos_protocol_select)}, - {"native_set_gps_lock", - "(I)Z", - reinterpret_cast(android_location_GnssLocationProvider_set_gps_lock)}, - {"native_set_emergency_supl_pdn", - "(I)Z", - reinterpret_cast(android_location_GnssLocationProvider_set_emergency_supl_pdn)}, - {"native_set_satellite_blacklist", - "([I[I)Z", - reinterpret_cast(android_location_GnssLocationProvider_set_satellite_blacklist)}, }; static const JNINativeMethod sMethodsBatching[] = { @@ -2663,6 +2700,42 @@ static const JNINativeMethod sNetworkConnectivityMethods[] = { reinterpret_cast(android_location_GnssNetworkConnectivityHandler_agps_data_conn_failed)}, }; +static const JNINativeMethod sConfigurationMethods[] = { + /* name, signature, funcPtr */ + {"native_get_gnss_configuration_version", + "()Lcom/android/server/location/GnssConfiguration$HalInterfaceVersion;", + reinterpret_cast( + android_location_GnssConfiguration_get_gnss_configuration_version)}, + {"native_set_supl_es", + "(I)Z", + reinterpret_cast(android_location_GnssConfiguration_set_supl_es)}, + {"native_set_supl_version", + "(I)Z", + reinterpret_cast(android_location_GnssConfiguration_set_supl_version)}, + {"native_set_supl_mode", + "(I)Z", + reinterpret_cast(android_location_GnssConfiguration_set_supl_mode)}, + {"native_set_lpp_profile", + "(I)Z", + reinterpret_cast(android_location_GnssConfiguration_set_lpp_profile)}, + {"native_set_gnss_pos_protocol_select", + "(I)Z", + reinterpret_cast( + android_location_GnssConfiguration_set_gnss_pos_protocol_select)}, + {"native_set_gps_lock", + "(I)Z", + reinterpret_cast(android_location_GnssConfiguration_set_gps_lock)}, + {"native_set_emergency_supl_pdn", + "(I)Z", + reinterpret_cast(android_location_GnssConfiguration_set_emergency_supl_pdn)}, + {"native_set_satellite_blacklist", + "([I[I)Z", + reinterpret_cast(android_location_GnssConfiguration_set_satellite_blacklist)}, + {"native_set_es_extension_sec", + "(I)Z", + reinterpret_cast(android_location_GnssConfiguration_set_es_extension_sec)}, +}; + int register_android_server_location_GnssLocationProvider(JNIEnv* env) { jniRegisterNativeMethods( env, @@ -2689,6 +2762,11 @@ int register_android_server_location_GnssLocationProvider(JNIEnv* env) { "com/android/server/location/GnssNetworkConnectivityHandler", sNetworkConnectivityMethods, NELEM(sNetworkConnectivityMethods)); + jniRegisterNativeMethods( + env, + "com/android/server/location/GnssConfiguration", + sConfigurationMethods, + NELEM(sConfigurationMethods)); return jniRegisterNativeMethods( env, "com/android/server/location/GnssLocationProvider", -- cgit v1.2.3-59-g8ed1b