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

Commit 5409f76f authored by Anil Admal's avatar Anil Admal Committed by Android (Google) Code Review
Browse files

Merge "Update getGnssCapabilities() in LMS to include sub-HAL capabilities (part 2)"

parents 34ac2af0 312fddb3
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -77,15 +77,14 @@ public final class GnssCapabilities {
    })
    public @interface Capability {}

    /**
     * @hide
     */
    /** @hide */
    public static final long INVALID_CAPABILITIES = -1;

    /** A bitmask of supported GNSS capabilities. */
    private final long mGnssCapabilities;

    static GnssCapabilities of(long gnssCapabilities) {
    /** @hide */
    public static GnssCapabilities of(long gnssCapabilities) {
        return new GnssCapabilities(gnssCapabilities);
    }

+7 −4
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import android.location.Address;
import android.location.Criteria;
import android.location.GeocoderParams;
import android.location.Geofence;
import android.location.GnssCapabilities;
import android.location.GnssMeasurementCorrections;
import android.location.IBatchedLocationCallback;
import android.location.IGnssMeasurementsListener;
@@ -102,6 +103,7 @@ import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
import com.android.server.location.GeofenceProxy;
import com.android.server.location.GnssBatchingProvider;
import com.android.server.location.GnssCapabilitiesProvider;
import com.android.server.location.GnssLocationProvider;
import com.android.server.location.GnssMeasurementCorrectionsProvider;
import com.android.server.location.GnssMeasurementsProvider;
@@ -249,8 +251,8 @@ public class LocationManagerService extends ILocationManager.Stub {
    private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};

    private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;

    private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
    private GnssCapabilitiesProvider mGnssCapabilitiesProvider;

    private GnssBatchingProvider mGnssBatchingProvider;
    @GuardedBy("mLock")
@@ -773,6 +775,7 @@ public class LocationManagerService extends ILocationManager.Stub {
            mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
            mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
            mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
            mGnssCapabilitiesProvider = gnssProvider.getGnssCapabilitiesProvider();
            mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
            mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
            mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
@@ -2970,10 +2973,10 @@ public class LocationManagerService extends ILocationManager.Stub {
        mContext.enforceCallingPermission(
                android.Manifest.permission.LOCATION_HARDWARE,
                "Location Hardware permission not granted to obtain GNSS chipset capabilities.");
        if (!hasGnssPermissions(packageName) || mGnssMeasurementCorrectionsProvider == null) {
            return -1;
        if (!hasGnssPermissions(packageName) || mGnssCapabilitiesProvider == null) {
            return GnssCapabilities.INVALID_CAPABILITIES;
        }
        return mGnssMeasurementCorrectionsProvider.getCapabilities();
        return mGnssCapabilitiesProvider.getGnssCapabilities();
    }

    @Override
+143 −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.GnssCapabilities;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;

/**
 * Provides GNSS capabilities supported by the GNSS HAL implementation.
 */
public class GnssCapabilitiesProvider {
    private static final String TAG = "GnssCapabilitiesProvider";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    // Bit masks for capabilities in {@link android.location.GnssCapabilities}.
    private static final long GNSS_CAPABILITY_LOW_POWER_MODE =
            1L << GnssCapabilities.LOW_POWER_MODE;
    private static final long GNSS_CAPABILITY_SATELLITE_BLACKLIST =
            1L << GnssCapabilities.SATELLITE_BLACKLIST;
    private static final long GNSS_CAPABILITY_GEOFENCING = 1L << GnssCapabilities.GEOFENCING;
    private static final long GNSS_CAPABILITY_MEASUREMENTS = 1L << GnssCapabilities.MEASUREMENTS;
    private static final long GNSS_CAPABILITY_NAV_MESSAGES = 1L << GnssCapabilities.NAV_MESSAGES;
    private static final long GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS =
            1L << GnssCapabilities.MEASUREMENT_CORRECTIONS;
    private static final long GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_LOS_SATS =
            1L << GnssCapabilities.MEASUREMENT_CORRECTIONS_LOS_SATS;
    private static final long GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH =
            1L << GnssCapabilities.MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH;
    private static final long GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_REFLECTING_PLANE =
            1L << GnssCapabilities.MEASUREMENT_CORRECTIONS_REFLECTING_PLANE;

    private static final long GNSS_CAPABILITIES_TOP_HAL =
            GNSS_CAPABILITY_LOW_POWER_MODE | GNSS_CAPABILITY_SATELLITE_BLACKLIST
                    | GNSS_CAPABILITY_GEOFENCING | GNSS_CAPABILITY_MEASUREMENTS
                    | GNSS_CAPABILITY_NAV_MESSAGES;

    private static final long GNSS_CAPABILITIES_SUB_HAL_MEASUREMENT_CORRECTIONS =
            GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS
                    | GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_LOS_SATS
                    | GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH
                    | GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_REFLECTING_PLANE;

    // Capabilities in {@link android.location.GnssCapabilities} supported by GNSS chipset.
    @GuardedBy("this")
    private long mGnssCapabilities;

    /**
     * Returns the capabilities supported by the GNSS chipset.
     *
     * <p>The capabilities are described in {@link android.location.GnssCapabilities} and
     * their integer values correspond to the bit positions in the returned {@code long} value.
     */
    public long getGnssCapabilities() {
        synchronized (this) {
            return mGnssCapabilities;
        }
    }

    /**
     * Updates the general capabilities exposed through {@link android.location.GnssCapabilities}.
     */
    void setTopHalCapabilities(int topHalCapabilities,
            boolean hasGeofencingCapability, boolean hasMeasurementsCapability,
            boolean hasNavMessagesCapability) {
        long gnssCapabilities = 0;
        if (hasCapability(topHalCapabilities,
                GnssLocationProvider.GPS_CAPABILITY_LOW_POWER_MODE)) {
            gnssCapabilities |= GNSS_CAPABILITY_LOW_POWER_MODE;
        }
        if (hasCapability(topHalCapabilities,
                GnssLocationProvider.GPS_CAPABILITY_SATELLITE_BLACKLIST)) {
            gnssCapabilities |= GNSS_CAPABILITY_SATELLITE_BLACKLIST;
        }
        if (hasGeofencingCapability) {
            gnssCapabilities |= GNSS_CAPABILITY_GEOFENCING;
        }
        if (hasMeasurementsCapability) {
            gnssCapabilities |= GNSS_CAPABILITY_MEASUREMENTS;
        }
        if (hasNavMessagesCapability) {
            gnssCapabilities |= GNSS_CAPABILITY_NAV_MESSAGES;
        }

        synchronized (this) {
            mGnssCapabilities &= ~GNSS_CAPABILITIES_TOP_HAL;
            mGnssCapabilities |= gnssCapabilities;
            if (DEBUG) {
                Log.d(TAG, "setTopHalCapabilities, mGnssCapabilities=0x" + Long.toHexString(
                        mGnssCapabilities) + ", " + GnssCapabilities.of(mGnssCapabilities));
            }
        }
    }

    /**
     * Updates the measurement corrections related capabilities exposed through
     * {@link android.location.GnssCapabilities}.
     */
    void setSubHalMeasurementCorrectionsCapabilities(int measurementCorrectionsCapabilities) {
        long gnssCapabilities = GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS;
        if (hasCapability(measurementCorrectionsCapabilities,
                GnssMeasurementCorrectionsProvider.CAPABILITY_LOS_SATS)) {
            gnssCapabilities |= GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_LOS_SATS;
        }
        if (hasCapability(measurementCorrectionsCapabilities,
                GnssMeasurementCorrectionsProvider.CAPABILITY_EXCESS_PATH_LENGTH)) {
            gnssCapabilities |= GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH;
        }
        if (hasCapability(measurementCorrectionsCapabilities,
                GnssMeasurementCorrectionsProvider.CAPABILITY_REFLECTING_PLANE)) {
            gnssCapabilities |= GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_REFLECTING_PLANE;
        }

        synchronized (this) {
            mGnssCapabilities &= ~GNSS_CAPABILITIES_SUB_HAL_MEASUREMENT_CORRECTIONS;
            mGnssCapabilities |= gnssCapabilities;
            if (DEBUG) {
                Log.d(TAG, "setSubHalMeasurementCorrectionsCapabilities, mGnssCapabilities=0x"
                        + Long.toHexString(mGnssCapabilities) + ", " + GnssCapabilities.of(
                        mGnssCapabilities));
            }
        }
    }

    private static  boolean hasCapability(int halCapabilities, int capability) {
        return (halCapabilities & capability) != 0;
    }
}
+52 −23
Original line number Diff line number Diff line
@@ -173,8 +173,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
    public static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040;
    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;
    static final int GPS_CAPABILITY_LOW_POWER_MODE = 0x0000100;
    static final int GPS_CAPABILITY_SATELLITE_BLACKLIST = 0x0000200;

    // The AGPS SUPL mode
    private static final int AGPS_SUPL_MODE_MSA = 0x02;
@@ -338,8 +338,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
    // true if we started navigation
    private boolean mStarted;

    // capabilities of the GPS engine
    private volatile int mEngineCapabilities;
    // capabilities reported through the top level IGnssCallback.hal
    private volatile int mTopHalCapabilities;

    // true if XTRA is supported
    private boolean mSupportsXtra;
@@ -385,6 +385,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
    private final NtpTimeHelper mNtpTimeHelper;
    private final GnssBatchingProvider mGnssBatchingProvider;
    private final GnssGeofenceProvider mGnssGeofenceProvider;
    private final GnssCapabilitiesProvider mGnssCapabilitiesProvider;

    // Available only on GNSS HAL 2.0 implementations and later.
    private GnssVisibilityControl mGnssVisibilityControl;

@@ -593,10 +595,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
        mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
        mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);

        mNetworkConnectivityHandler = new GnssNetworkConnectivityHandler(
                context,
                GnssLocationProvider.this::onNetworkAvailable,
                looper);
        mNetworkConnectivityHandler = new GnssNetworkConnectivityHandler(context,
                GnssLocationProvider.this::onNetworkAvailable, looper);

        // App ops service to keep track of who is accessing the GPS
        mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -614,6 +614,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
        // while IO initialization and registration is delegated to our internal handler
        // this approach is just fine because events are posted to our handler anyway
        mGnssConfiguration = new GnssConfiguration(mContext);
        mGnssCapabilitiesProvider = new GnssCapabilitiesProvider();
        // Create a GPS net-initiated handler (also needed by handleInitialize)
        mNIHandler = new GpsNetInitiatedHandler(context,
                mNetInitiatedListener,
@@ -1280,12 +1281,8 @@ 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);
        return (mTopHalCapabilities & capability) != 0;
    }

    @NativeEntryPoint
@@ -1493,27 +1490,52 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
    }

    @NativeEntryPoint
    private void setEngineCapabilities(final int capabilities, boolean hasSubHalCapabilityFlags) {
        // send to handler thread for fast native return, and in-order handling
    private void setTopHalCapabilities(int topHalCapabilities, 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.
        mHandler.post(() -> {
            mEngineCapabilities = capabilities;
            mTopHalCapabilities = topHalCapabilities;

            if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) {
                mNtpTimeHelper.enablePeriodicTimeInjection();
                requestUtcTime();
            }

            mGnssMeasurementsProvider.onCapabilitiesUpdated(capabilities, hasSubHalCapabilityFlags);
            mGnssNavigationMessageProvider.onCapabilitiesUpdated(capabilities,
                    hasSubHalCapabilityFlags);
            boolean hasGeofencingCapability;
            boolean hasMeasurementsCapability;
            boolean hasNavMessagesCapability;
            if (hasSubHalCapabilityFlags) {
                hasGeofencingCapability = hasCapability(GPS_CAPABILITY_GEOFENCING);
                hasMeasurementsCapability = hasCapability(GPS_CAPABILITY_MEASUREMENTS);
                hasNavMessagesCapability = hasCapability(GPS_CAPABILITY_NAV_MESSAGES);
            } else {
                hasGeofencingCapability = mGnssGeofenceProvider.isHardwareGeofenceSupported();
                hasMeasurementsCapability = mGnssMeasurementsProvider.isAvailableInPlatform();
                hasNavMessagesCapability = mGnssNavigationMessageProvider.isAvailableInPlatform();
            }

            mGnssMeasurementsProvider.onCapabilitiesUpdated(hasMeasurementsCapability);
            mGnssNavigationMessageProvider.onCapabilitiesUpdated(hasNavMessagesCapability);
            restartRequests();

            mGnssCapabilitiesProvider.setTopHalCapabilities(topHalCapabilities,
                    hasGeofencingCapability, hasMeasurementsCapability, hasNavMessagesCapability);
        });
    }

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

            mGnssCapabilitiesProvider.setSubHalMeasurementCorrectionsCapabilities(
                    subHalCapabilities);
        });
    }

    private void restartRequests() {
@@ -1614,6 +1636,13 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
        return () -> mGnssMetrics.dumpGnssMetricsAsProtoString();
    }

    /**
     * @hide
     */
    public GnssCapabilitiesProvider getGnssCapabilitiesProvider() {
        return mGnssCapabilitiesProvider;
    }

    @NativeEntryPoint
    private void reportLocationBatch(Location[] locationArray) {
        List<Location> locations = new ArrayList<>(Arrays.asList(locationArray));
@@ -2143,7 +2172,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
        s.append("  mGnssNavigationMessageProvider.isRegistered()=")
                .append(mGnssNavigationMessageProvider.isRegistered()).append('\n');
        s.append("  mDisableGpsForPowerManager=").append(mDisableGpsForPowerManager).append('\n');
        s.append("  mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities));
        s.append("  mTopHalCapabilities=0x").append(Integer.toHexString(mTopHalCapabilities));
        s.append(" ( ");
        if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHEDULING ");
        if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
+11 −9
Original line number Diff line number Diff line
@@ -34,9 +34,9 @@ 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;
    static final int CAPABILITY_LOS_SATS = 0x0000001;
    static final int CAPABILITY_EXCESS_PATH_LENGTH = 0x0000002;
    static final int CAPABILITY_REFLECTING_PLANE = 0x0000004;

    private static final int INVALID_CAPABILITIES = 1 << 31;

@@ -83,21 +83,23 @@ public class GnssMeasurementCorrectionsProvider {
    }

    /** Handle measurement corrections capabilities update from the GNSS HAL implementation. */
    void onCapabilitiesUpdated(int capabilities) {
    boolean onCapabilitiesUpdated(int capabilities) {
        if (hasCapability(capabilities, CAPABILITY_LOS_SATS) || hasCapability(capabilities,
                CAPABILITY_EXCESS_PATH_LENGTH)) {
            mCapabilities = capabilities;
            return true;
        } 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.");
            return false;
        }
    }

    /**
     * Returns the measurement corrections specific capabilities of the GNSS HAL implementation.
     */
    public int getCapabilities() {
    int getCapabilities() {
        return mCapabilities;
    }

@@ -122,14 +124,14 @@ public class GnssMeasurementCorrectionsProvider {
        return s.toString();
    }

    private boolean isCapabilitiesReceived() {
        return mCapabilities != INVALID_CAPABILITIES;
    }

    private static  boolean hasCapability(int halCapabilities, int capability) {
        return (halCapabilities & capability) != 0;
    }

    private boolean isCapabilitiesReceived() {
        return mCapabilities != INVALID_CAPABILITIES;
    }

    @VisibleForTesting
    static class GnssMeasurementCorrectionsProviderNative {
        public boolean isMeasurementCorrectionsSupported() {
Loading