Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit efd9dc6e authored by Anil Admal's avatar Anil Admal
Browse files

Add new GNSS capabilities for year of hardware deprecation (framework)

The following capabilities need to be added to the GNSS HAL interface
to enforce support through the CTS/VTS tests.

-Add low power mode capability.
-Add satellite blacklisting capability.
-Add measurement corrections capability and move capabilities in
 IGnssCallback.hal that are specific to measurement correctons
 to its own sub-HAL measurement_corrections@1.0.

Bug: 128028791
Bug: 127434062
Bug: 128309220
Test: Tested on cuttlefish using default implementation and VTS tests
Change-Id: I95c76b276afef5f0ffc14dc08bf618530d6a1bd9
parent 0b464921
Loading
Loading
Loading
Loading
+16 −6
Original line number Diff line number Diff line
@@ -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
+54 −16
Original line number Diff line number Diff line
@@ -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,10 +1484,9 @@ 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(
                () -> {
        mHandler.post(() -> {
            mEngineCapabilities = capabilities;

            if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) {
@@ -1478,13 +1494,19 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
                requestUtcTime();
            }

                    mGnssMeasurementsProvider.onCapabilitiesUpdated(capabilities);
                    mGnssNavigationMessageProvider.onCapabilitiesUpdated(
                            hasCapability(GPS_CAPABILITY_NAV_MESSAGES));
            mGnssMeasurementsProvider.onCapabilitiesUpdated(capabilities, hasSubHalCapabilityFlags);
            mGnssNavigationMessageProvider.onCapabilitiesUpdated(capabilities,
                    hasSubHalCapabilityFlags);
            restartRequests();
        });
    }

    @NativeEntryPoint
    private void setMeasurementCorrectionsCapabilities(final int capabilities) {
        mHandler.post(() -> mGnssMeasurementCorrectionsProvider.onCapabilitiesUpdated(
                capabilities));
    }

    private void restartRequests() {
        Log.i(TAG, "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");
+149 −0
Original line number Diff line number Diff line
/*
 * 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.
 *
 * <p>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);
}
+11 −36
Original line number Diff line number Diff line
@@ -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);
}
+11 −3
Original line number Diff line number Diff line
@@ -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();
    }
Loading