diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 7fab2b96ddbe1..64970fbda76b9 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -102,6 +102,7 @@ import com.android.server.location.GeofenceManager; import com.android.server.location.GeofenceProxy; import com.android.server.location.GnssBatchingProvider; import com.android.server.location.GnssLocationProvider; +import com.android.server.location.GnssMeasurementCorrectionsProvider; import com.android.server.location.GnssMeasurementsProvider; import com.android.server.location.GnssNavigationMessageProvider; import com.android.server.location.GnssStatusListenerHelper; @@ -195,6 +196,7 @@ public class LocationManagerService extends ILocationManager.Stub { private PassiveProvider mPassiveProvider; // track passive provider for special cases private LocationBlacklist mBlacklist; private GnssMeasurementsProvider mGnssMeasurementsProvider; + private GnssMeasurementCorrectionsProvider mGnssMeasurementCorrectionsProvider; private GnssNavigationMessageProvider mGnssNavigationMessageProvider; @GuardedBy("mLock") private String mLocationControllerExtraPackage; @@ -757,6 +759,8 @@ public class LocationManagerService extends ILocationManager.Stub { mGnssStatusProvider = gnssProvider.getGnssStatusProvider(); mNetInitiatedListener = gnssProvider.getNetInitiatedListener(); mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider(); + mGnssMeasurementCorrectionsProvider = + gnssProvider.getGnssMeasurementCorrectionsProvider(); mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider(); mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy(); } @@ -2921,22 +2925,28 @@ public class LocationManagerService extends ILocationManager.Stub { mContext.enforceCallingPermission( android.Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to inject GNSS measurement corrections."); - if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) { + if (!hasGnssPermissions(packageName)) { Slog.e(TAG, "Can not inject GNSS corrections due to no permission."); - } else { - mGnssMeasurementsProvider.injectGnssMeasurementCorrections(measurementCorrections); + return; } + if (mGnssMeasurementCorrectionsProvider == null) { + Slog.e(TAG, "Can not inject GNSS corrections. GNSS measurement corrections provider " + + "not available."); + return; + } + mGnssMeasurementCorrectionsProvider.injectGnssMeasurementCorrections( + measurementCorrections); } @Override public int getGnssCapabilities(String packageName) { mContext.enforceCallingPermission( android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to obrain GNSS chipset capabilities."); - if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) { + "Location Hardware permission not granted to obtain GNSS chipset capabilities."); + if (!hasGnssPermissions(packageName) || mGnssMeasurementCorrectionsProvider == null) { return -1; } - return mGnssMeasurementsProvider.getGnssCapabilities(); + return mGnssMeasurementCorrectionsProvider.getCapabilities(); } @Override diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index c173d660803fb..8249999033a41 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -166,9 +166,15 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private static final int GPS_CAPABILITY_MSA = 0x0000004; private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008; private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010; - private static final int GPS_CAPABILITY_GEOFENCING = 0x0000020; + + // The following three capability flags are removed in IGnssCallback.hal@2.0 and their values + // are marked reserved and not reused in 2.0 to avoid confusion with prior versions. + public static final int GPS_CAPABILITY_GEOFENCING = 0x0000020; public static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040; - private static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080; + public static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080; + + private static final int GPS_CAPABILITY_LOW_POWER_MODE = 0x0000100; + private static final int GPS_CAPABILITY_SATELLITE_BLACKLIST = 0x0000200; // The AGPS SUPL mode private static final int AGPS_SUPL_MODE_MSA = 0x02; @@ -333,7 +339,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private boolean mStarted; // capabilities of the GPS engine - private int mEngineCapabilities; + private volatile int mEngineCapabilities; // true if XTRA is supported private boolean mSupportsXtra; @@ -372,6 +378,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private final LocationExtras mLocationExtras = new LocationExtras(); private final GnssStatusListenerHelper mGnssStatusListenerHelper; private final GnssMeasurementsProvider mGnssMeasurementsProvider; + private final GnssMeasurementCorrectionsProvider mGnssMeasurementCorrectionsProvider; private final GnssNavigationMessageProvider mGnssNavigationMessageProvider; private final LocationChangeListener mNetworkLocationListener = new NetworkLocationListener(); private final LocationChangeListener mFusedLocationListener = new FusedLocationListener(); @@ -437,6 +444,10 @@ public class GnssLocationProvider extends AbstractLocationProvider implements return mGnssMeasurementsProvider; } + public GnssMeasurementCorrectionsProvider getGnssMeasurementCorrectionsProvider() { + return mGnssMeasurementCorrectionsProvider; + } + public GnssNavigationMessageProvider getGnssNavigationMessageProvider() { return mGnssNavigationMessageProvider; } @@ -627,6 +638,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements } }; + mGnssMeasurementCorrectionsProvider = new GnssMeasurementCorrectionsProvider(mHandler); + mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(mContext, mHandler) { @Override protected boolean isGpsEnabled() { @@ -1258,6 +1271,10 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent); } + public int getGnssCapabilities() { + return mEngineCapabilities; + } + private boolean hasCapability(int capability) { return ((mEngineCapabilities & capability) != 0); } @@ -1467,22 +1484,27 @@ public class GnssLocationProvider extends AbstractLocationProvider implements } @NativeEntryPoint - private void setEngineCapabilities(final int capabilities) { + private void setEngineCapabilities(final int capabilities, boolean hasSubHalCapabilityFlags) { // send to handler thread for fast native return, and in-order handling - mHandler.post( - () -> { - mEngineCapabilities = capabilities; + mHandler.post(() -> { + mEngineCapabilities = capabilities; - if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) { - mNtpTimeHelper.enablePeriodicTimeInjection(); - requestUtcTime(); - } + if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) { + mNtpTimeHelper.enablePeriodicTimeInjection(); + requestUtcTime(); + } - mGnssMeasurementsProvider.onCapabilitiesUpdated(capabilities); - mGnssNavigationMessageProvider.onCapabilitiesUpdated( - hasCapability(GPS_CAPABILITY_NAV_MESSAGES)); - restartRequests(); - }); + mGnssMeasurementsProvider.onCapabilitiesUpdated(capabilities, hasSubHalCapabilityFlags); + mGnssNavigationMessageProvider.onCapabilitiesUpdated(capabilities, + hasSubHalCapabilityFlags); + restartRequests(); + }); + } + + @NativeEntryPoint + private void setMeasurementCorrectionsCapabilities(final int capabilities) { + mHandler.post(() -> mGnssMeasurementCorrectionsProvider.onCapabilitiesUpdated( + capabilities)); } private void restartRequests() { @@ -2122,7 +2144,23 @@ public class GnssLocationProvider extends AbstractLocationProvider implements if (hasCapability(GPS_CAPABILITY_GEOFENCING)) s.append("GEOFENCING "); if (hasCapability(GPS_CAPABILITY_MEASUREMENTS)) s.append("MEASUREMENTS "); if (hasCapability(GPS_CAPABILITY_NAV_MESSAGES)) s.append("NAV_MESSAGES "); + if (hasCapability(GPS_CAPABILITY_LOW_POWER_MODE)) s.append("LOW_POWER_MODE "); + if (hasCapability(GPS_CAPABILITY_SATELLITE_BLACKLIST)) s.append("SATELLITE_BLACKLIST "); s.append(")\n"); + if (mGnssGeofenceProvider.isHardwareGeofenceSupported()) { + s.append(" hasSubHal=GEOFENCING\n"); + } + if (mGnssMeasurementsProvider.isAvailableInPlatform()) { + s.append(" hasSubHal=MEASUREMENTS\n"); + } + if (mGnssNavigationMessageProvider.isAvailableInPlatform()) { + s.append(" hasSubHal=NAV_MESSAGES\n"); + } + if (mGnssMeasurementCorrectionsProvider.isAvailableInPlatform()) { + s.append(" hasSubHal=MEASUREMENT_CORRECTIONS ["); + s.append(mGnssMeasurementCorrectionsProvider.toStringCapabilities()); + s.append("]\n"); + } s.append(mGnssMetrics.dumpGnssMetricsAsText()); s.append(" native internal state: ").append(native_get_internal_state()); s.append("\n"); diff --git a/services/core/java/com/android/server/location/GnssMeasurementCorrectionsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementCorrectionsProvider.java new file mode 100644 index 0000000000000..21627876a49e1 --- /dev/null +++ b/services/core/java/com/android/server/location/GnssMeasurementCorrectionsProvider.java @@ -0,0 +1,149 @@ +/* + * 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.location.GnssMeasurementCorrections; +import android.os.Handler; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; + +/** + * Manages GNSS measurement corrections. + * + *

Implements the framework side of the GNSS HAL interfaces {@code IMeasurementCorrections.hal} + * and {@code IMeasurementCorrectionsCallback.hal). + * + * @hide + */ +public class GnssMeasurementCorrectionsProvider { + private static final String TAG = "GnssMeasurementCorrectionsProvider"; + + // These must match with the Capabilities enum in IMeasurementCorrectionsCallback.hal. + private static final int CAPABILITY_LOS_SATS = 0x0000001; + private static final int CAPABILITY_EXCESS_PATH_LENGTH = 0x0000002; + private static final int CAPABILITY_REFLECTING_PLANE = 0x0000004; + + private static final int INVALID_CAPABILITIES = 1 << 31; + + private final Handler mHandler; + private final GnssMeasurementCorrectionsProviderNative mNative; + private volatile int mCapabilities = INVALID_CAPABILITIES; + + GnssMeasurementCorrectionsProvider(Handler handler) { + this(handler, new GnssMeasurementCorrectionsProviderNative()); + } + + @VisibleForTesting + GnssMeasurementCorrectionsProvider(Handler handler, + GnssMeasurementCorrectionsProviderNative aNative) { + mHandler = handler; + mNative = aNative; + } + + /** + * Returns {@code true} if the GNSS HAL implementation supports measurement corrections. + */ + public boolean isAvailableInPlatform() { + return mNative.isMeasurementCorrectionsSupported(); + } + + /** + * Injects GNSS measurement corrections into the GNSS chipset. + * + * @param measurementCorrections a {@link GnssMeasurementCorrections} object with the GNSS + * measurement corrections to be injected into the GNSS chipset. + */ + public void injectGnssMeasurementCorrections( + GnssMeasurementCorrections measurementCorrections) { + if (!isCapabilitiesReceived()) { + Log.w(TAG, "Failed to inject GNSS measurement corrections. Capabilities " + + "not received yet."); + return; + } + mHandler.post(() -> { + if (!mNative.injectGnssMeasurementCorrections(measurementCorrections)) { + Log.e(TAG, "Failure in injecting GNSS corrections."); + } + }); + } + + /** Handle measurement corrections capabilities update from the GNSS HAL implementation. */ + void onCapabilitiesUpdated(int capabilities) { + if (hasCapability(capabilities, CAPABILITY_LOS_SATS) || hasCapability(capabilities, + CAPABILITY_EXCESS_PATH_LENGTH)) { + mCapabilities = capabilities; + } else { + Log.e(TAG, "Failed to set capabilities. Received capabilities 0x" + + Integer.toHexString(capabilities) + " does not contain the mandatory " + + "LOS_SATS or the EXCESS_PATH_LENGTH capability."); + } + } + + /** + * Returns the measurement corrections specific capabilities of the GNSS HAL implementation. + */ + public int getCapabilities() { + return mCapabilities; + } + + /** + * Returns the string representation of the GNSS measurement capabilities. + */ + String toStringCapabilities() { + final int capabilities = getCapabilities(); + StringBuilder s = new StringBuilder(); + s.append("mCapabilities=0x").append(Integer.toHexString(capabilities)); + s.append(" ( "); + if (hasCapability(capabilities, CAPABILITY_LOS_SATS)) { + s.append("LOS_SATS "); + } + if (hasCapability(capabilities, CAPABILITY_EXCESS_PATH_LENGTH)) { + s.append("EXCESS_PATH_LENGTH "); + } + if (hasCapability(capabilities, CAPABILITY_REFLECTING_PLANE)) { + s.append("REFLECTING_PLANE "); + } + s.append(")"); + return s.toString(); + } + + private boolean isCapabilitiesReceived() { + return mCapabilities != INVALID_CAPABILITIES; + } + + private static boolean hasCapability(int halCapabilities, int capability) { + return (halCapabilities & capability) != 0; + } + + @VisibleForTesting + static class GnssMeasurementCorrectionsProviderNative { + public boolean isMeasurementCorrectionsSupported() { + return native_is_measurement_corrections_supported(); + } + + public boolean injectGnssMeasurementCorrections( + GnssMeasurementCorrections measurementCorrections) { + return native_inject_gnss_measurement_corrections(measurementCorrections); + } + } + + private static native boolean native_is_measurement_corrections_supported(); + + private static native boolean native_inject_gnss_measurement_corrections( + GnssMeasurementCorrections measurementCorrections); +} diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java index 1fc7192916dff..844735a02eeb8 100644 --- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java +++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java @@ -11,13 +11,12 @@ * 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 + * limitations under the License. */ package com.android.server.location; import android.content.Context; -import android.location.GnssMeasurementCorrections; import android.location.GnssMeasurementsEvent; import android.location.IGnssMeasurementsListener; import android.os.Handler; @@ -42,7 +41,6 @@ public abstract class GnssMeasurementsProvider private boolean mIsCollectionStarted; private boolean mEnableFullTracking; - private int mGnssEngineCapabilities; protected GnssMeasurementsProvider(Context context, Handler handler) { this(context, handler, new GnssMeasurementProviderNative()); @@ -87,21 +85,6 @@ public abstract class GnssMeasurementsProvider } } - /** - * Injects GNSS measurement corrections into the GNSS chipset. - * - * @param measurementCorrections a {@link GnssMeasurementCorrections} object with the GNSS - * measurement corrections to be injected into the GNSS chipset. - */ - public void injectGnssMeasurementCorrections( - GnssMeasurementCorrections measurementCorrections) { - mHandler.post(() -> { - if (!mNative.injectGnssMeasurementCorrections(measurementCorrections)) { - Log.e(TAG, "Failure in injecting GNSS corrections."); - } - }); - } - @Override protected void unregisterFromService() { boolean stopped = mNative.stopMeasurementCollection(); @@ -121,20 +104,20 @@ public abstract class GnssMeasurementsProvider }); } - /** Updates the framework about the capabilities of the GNSS chipset */ - public void onCapabilitiesUpdated(int capabilities) { - mGnssEngineCapabilities = capabilities; - boolean isGnssMeasurementsSupported = - (capabilities & GnssLocationProvider.GPS_CAPABILITY_MEASUREMENTS) != 0; + /** Handle GNSS capabilities update from the GNSS HAL implementation. */ + public void onCapabilitiesUpdated(int capabilities, boolean hasSubHalCapabilityFlags) { + // The IGnssCallback.hal@2.0 removed sub-HAL capability flags from the Capabilities enum + // and instead uses the sub-HAL non-null handle returned from IGnss.hal@2.0 to indicate + // support. Therefore, the 'hasSubHalCapabilityFlags' parameter is needed to tell if the + // 'capabilities' parameter includes the sub-HAL capability flags or not. Old HALs + // which explicitly set the sub-HAL capability bits must continue to work. + final boolean isGnssMeasurementsSupported = hasSubHalCapabilityFlags + ? (capabilities & GnssLocationProvider.GPS_CAPABILITY_MEASUREMENTS) != 0 + : mNative.isMeasurementSupported(); setSupported(isGnssMeasurementsSupported); updateResult(); } - /** Obtains the GNSS engine capabilities. */ - public int getGnssCapabilities() { - return mGnssEngineCapabilities; - } - public void onGpsEnabledChanged() { tryUpdateRegistrationWithService(); updateResult(); @@ -195,11 +178,6 @@ public abstract class GnssMeasurementsProvider public boolean stopMeasurementCollection() { return native_stop_measurement_collection(); } - - public boolean injectGnssMeasurementCorrections( - GnssMeasurementCorrections measurementCorrections) { - return native_inject_gnss_measurement_corrections(measurementCorrections); - } } private static native boolean native_is_measurement_supported(); @@ -207,7 +185,4 @@ public abstract class GnssMeasurementsProvider private static native boolean native_start_measurement_collection(boolean enableFullTracking); private static native boolean native_stop_measurement_collection(); - - private static native boolean native_inject_gnss_measurement_corrections( - GnssMeasurementCorrections measurementCorrections); } diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java index 80a3f9bd2aba2..7e8b599129c36 100644 --- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java +++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.location; @@ -51,7 +51,6 @@ public abstract class GnssNavigationMessageProvider mNative = aNative; } - // TODO(b/37460011): Use this with death recovery logic. void resumeIfStarted() { if (DEBUG) { Log.d(TAG, "resumeIfStarted"); @@ -92,7 +91,16 @@ public abstract class GnssNavigationMessageProvider ); } - public void onCapabilitiesUpdated(boolean isGnssNavigationMessageSupported) { + /** Handle GNSS capabilities update from the GNSS HAL implementation */ + public void onCapabilitiesUpdated(int capabilities, boolean hasSubHalCapabilityFlags) { + // The IGnssCallback.hal@2.0 removed sub-HAL capability flags from the Capabilities enum + // and instead uses the sub-HAL non-null handle returned from IGnss.hal@2.0 to indicate + // support. Therefore, the 'hasSubHalCapabilityFlags' parameter is needed to tell if the + // 'capabilities' parameter includes the sub-HAL capability flags or not. Old HALs + // which explicitly set the sub-HAL capability bits must continue to work. + final boolean isGnssNavigationMessageSupported = hasSubHalCapabilityFlags + ? (capabilities & GnssLocationProvider.GPS_CAPABILITY_NAV_MESSAGES) != 0 + : mNative.isNavigationMessageSupported(); setSupported(isGnssNavigationMessageSupported); updateResult(); } diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 050a07965b9c5..00b815ae1bfa7 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -109,6 +109,7 @@ cc_defaults { "android.hardware.gnss@1.0", "android.hardware.gnss@1.1", "android.hardware.gnss@2.0", + "android.hardware.gnss.measurement_corrections@1.0", "android.hardware.gnss.visibility_control@1.0", "android.hardware.input.classifier@1.0", "android.hardware.ir@1.0", diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index caba3afed41b3..a4955f07801a5 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -71,6 +71,7 @@ static jmethodID method_reportMeasurementData; static jmethodID method_reportNavigationMessages; static jmethodID method_reportLocationBatch; static jmethodID method_reportGnssServiceDied; +static jmethodID method_setMeasurementCorrectionsCapabilities; static jmethodID method_correctionsGetLatitudeDegrees; static jmethodID method_correctionsGetLongitudeDegrees; static jmethodID method_correctionsGetAltitudeMeters; @@ -158,10 +159,9 @@ using IAGnss_V2_0 = android::hardware::gnss::V2_0::IAGnss; using IAGnssCallback_V1_0 = android::hardware::gnss::V1_0::IAGnssCallback; using IAGnssCallback_V2_0 = android::hardware::gnss::V2_0::IAGnssCallback; -using IMeasurementCorrections = - android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections; -using GnssSingleSatCorrectionFlags = - android::hardware::gnss::measurement_corrections::V1_0::GnssSingleSatCorrectionFlags; +using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections; +using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback; +using android::hardware::gnss::measurement_corrections::V1_0::GnssSingleSatCorrectionFlags; using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl; using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControlCallback; @@ -201,7 +201,6 @@ sp gnssMeasurementIface_V1_1 = nullptr; sp gnssMeasurementIface_V2_0 = nullptr; sp gnssNavigationMessageIface = nullptr; sp gnssCorrectionsIface = nullptr; - sp gnssVisibilityControlIface = nullptr; #define WAKE_LOCK_NAME "GPS" @@ -572,7 +571,9 @@ struct GnssCallback : public IGnssCallback { template Return gnssLocationCbImpl(const T& location); - // TODO(b/73306084): Reconsider allocation cost vs threadsafety on these statics + Return gnssSetCapabilitesCbImpl(uint32_t capabilities, bool hasSubHalCapabilityFlags); + + // TODO: Reconsider allocation cost vs threadsafety on these statics static const char* sNmeaString; static size_t sNmeaStringLength; }; @@ -694,16 +695,29 @@ Return GnssCallback::gnssNmeaCb( } Return GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) { - ALOGD("%s: %du\n", __func__, capabilities); - - JNIEnv* env = getJniEnv(); - env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities); - checkAndClearExceptionFromCallback(env, __FUNCTION__); - return Void(); + return GnssCallback::gnssSetCapabilitesCbImpl(capabilities, + /* hasSubHalCapabilityFlags = */ true); } Return GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) { - return GnssCallback::gnssSetCapabilitesCb(capabilities); + return GnssCallback::gnssSetCapabilitesCbImpl(capabilities, + /* hasSubHalCapabilityFlags = */ false); +} + +Return GnssCallback::gnssSetCapabilitesCbImpl(uint32_t capabilities, + bool hasSubHalCapabilityFlags) { + // The IGnssCallback.hal@2.0 removed sub-HAL capability flags from the Capabilities enum + // and instead uses the sub-HAL non-null handle returned from IGnss.hal@2.0 to indicate + // support. Therefore, the 'hasSubHalCapabilityFlags' parameter is needed to tell if the + // 'capabilities' parameter includes the sub-HAL capability flags or not. Old HALs + // which explicitly set the sub-HAL capability bits must continue to work. + ALOGD("%s: capabilities=%du, hasSubHalCapabilityFlags=%d\n", __func__, capabilities, + hasSubHalCapabilityFlags); + JNIEnv* env = getJniEnv(); + env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities, + boolToJbool(hasSubHalCapabilityFlags)); + checkAndClearExceptionFromCallback(env, __FUNCTION__); + return Void(); } Return GnssCallback::gnssAcquireWakelockCb() { @@ -1152,6 +1166,22 @@ void GnssMeasurementCallback::setMeasurementData(JNIEnv* env, jobject clock, env->DeleteLocalRef(gnssMeasurementsEvent); } +/* + * MeasurementCorrectionsCallback implements callback methods of interface + * IMeasurementCorrectionsCallback.hal. + */ +struct MeasurementCorrectionsCallback : public IMeasurementCorrectionsCallback { + Return setCapabilitiesCb(uint32_t capabilities) override; +}; + +Return MeasurementCorrectionsCallback::setCapabilitiesCb(uint32_t capabilities) { + ALOGD("%s: %du\n", __func__, capabilities); + JNIEnv* env = getJniEnv(); + env->CallVoidMethod(mCallbacksObj, method_setMeasurementCorrectionsCapabilities, capabilities); + checkAndClearExceptionFromCallback(env, __FUNCTION__); + return Void(); +} + /* * GnssNiCallback implements callback methods required by the IGnssNi interface. */ @@ -1434,7 +1464,7 @@ static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "(I[I[F[F[F[F)V"); method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V"); method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V"); - method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V"); + method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(IZ)V"); method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V"); method_setGnssHardwareModelName = env->GetMethodID(clazz, "setGnssHardwareModelName", "(Ljava/lang/String;)V"); @@ -1474,6 +1504,9 @@ static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass "(Ljava/lang/String;BLjava/lang/String;BLjava/lang/String;BZZ)V"); method_isInEmergencySession = env->GetMethodID(clazz, "isInEmergencySession", "()Z"); + method_setMeasurementCorrectionsCapabilities = env->GetMethodID(clazz, + "setMeasurementCorrectionsCapabilities", "(I)V"); + jclass measCorrClass = env->FindClass("android/location/GnssMeasurementCorrections"); method_correctionsGetLatitudeDegrees = env->GetMethodID( measCorrClass,"getLatitudeDegrees", "()D"); @@ -1591,7 +1624,7 @@ static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass } if (gnssHal_V2_0 != nullptr) { - // TODO(b/119638366): getExtensionGnssMeasurement_1_1 from gnssHal_V2_0 + // TODO: getExtensionGnssMeasurement_1_1 from gnssHal_V2_0 auto gnssMeasurement = gnssHal_V2_0->getExtensionGnssMeasurement_2_0(); if (!gnssMeasurement.isOk()) { ALOGD("Unable to get a handle to GnssMeasurement_V2_0"); @@ -1795,6 +1828,12 @@ static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject gnssVisibilityControlIface->setCallback(gnssVisibilityControlCbIface); } + if (gnssCorrectionsIface != nullptr) { + sp gnssCorrectionsIfaceCbIface = + new MeasurementCorrectionsCallback(); + gnssCorrectionsIface->setCallback(gnssCorrectionsIfaceCbIface); + } + return JNI_TRUE; } @@ -2154,7 +2193,7 @@ static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* jobject /* obj */) { jstring result = nullptr; /* - * TODO(b/33089503) : Create a jobject to represent GnssDebug. + * TODO: Create a jobject to represent GnssDebug. */ std::stringstream internalState; @@ -2380,13 +2419,25 @@ static jboolean android_location_GnssMeasurementsProvider_stop_measurement_colle return boolToJbool(result.isOk()); } -static jboolean android_location_GnssMeasurementsProvider_inject_gnss_measurement_corrections( +static jboolean + android_location_GnssMeasurementCorrectionsProvider_is_measurement_corrections_supported( + JNIEnv* env, jclass clazz) { + if (gnssCorrectionsIface != nullptr) { + return JNI_TRUE; + } + + return JNI_FALSE; +} + +static jboolean + android_location_GnssMeasurementCorrectionsProvider_inject_gnss_measurement_corrections( JNIEnv* env, jobject obj /* clazz*/, jobject correctionsObj) { if (gnssCorrectionsIface == nullptr) { - ALOGW("Trying to inject GNSS corrections on a chipset that does not support them."); + ALOGW("Trying to inject GNSS measurement corrections on a chipset that does not" + " support them."); return JNI_FALSE; } @@ -2882,18 +2933,25 @@ static const JNINativeMethod sGeofenceMethods[] = { static const JNINativeMethod sMeasurementMethods[] = { /* name, signature, funcPtr */ {"native_is_measurement_supported", "()Z", - reinterpret_cast( - android_location_GnssMeasurementsProvider_is_measurement_supported)}, + reinterpret_cast( + android_location_GnssMeasurementsProvider_is_measurement_supported)}, {"native_start_measurement_collection", "(Z)Z", - reinterpret_cast( - android_location_GnssMeasurementsProvider_start_measurement_collection)}, + reinterpret_cast( + android_location_GnssMeasurementsProvider_start_measurement_collection)}, {"native_stop_measurement_collection", "()Z", - reinterpret_cast( - android_location_GnssMeasurementsProvider_stop_measurement_collection)}, + reinterpret_cast( + android_location_GnssMeasurementsProvider_stop_measurement_collection)}, +}; + +static const JNINativeMethod sMeasurementCorrectionsMethods[] = { + /* name, signature, funcPtr */ + {"native_is_measurement_corrections_supported", "()Z", + reinterpret_cast( + android_location_GnssMeasurementCorrectionsProvider_is_measurement_corrections_supported)}, {"native_inject_gnss_measurement_corrections", - "(Landroid/location/GnssMeasurementCorrections;)Z", - reinterpret_cast( - android_location_GnssMeasurementsProvider_inject_gnss_measurement_corrections)}, + "(Landroid/location/GnssMeasurementCorrections;)Z", + reinterpret_cast( + android_location_GnssMeasurementCorrectionsProvider_inject_gnss_measurement_corrections)}, }; static const JNINativeMethod sNavigationMessageMethods[] = { @@ -2990,6 +3048,11 @@ int register_android_server_location_GnssLocationProvider(JNIEnv* env) { "com/android/server/location/GnssMeasurementsProvider", sMeasurementMethods, NELEM(sMeasurementMethods)); + jniRegisterNativeMethods( + env, + "com/android/server/location/GnssMeasurementCorrectionsProvider", + sMeasurementCorrectionsMethods, + NELEM(sMeasurementCorrectionsMethods)); jniRegisterNativeMethods( env, "com/android/server/location/GnssNavigationMessageProvider",