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

Commit b983a450 authored by David Christie's avatar David Christie
Browse files

Add permission gated provider to access the hardware GPS directly.

-Only applicable when an app level GPS provider override is present which may mask the hardware provider.

Bug: 260010264
Test: atest LocationManagerServiceTest, atest LocationProviderManagerTest

Change-Id: I085152f9074863dcf8d8ee96981846b847966018
parent dc6b3f66
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -6246,6 +6246,7 @@ package android.location {
    method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(@NonNull android.location.BatchedLocationCallback);
    field public static final String ACTION_ADAS_GNSS_ENABLED_CHANGED = "android.location.action.ADAS_GNSS_ENABLED_CHANGED";
    field public static final String EXTRA_ADAS_GNSS_ENABLED = "android.location.extra.ADAS_GNSS_ENABLED";
    field @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public static final String GPS_HARDWARE_PROVIDER = "gps_hardware";
  }
  public final class LocationRequest implements android.os.Parcelable {
@@ -6385,6 +6386,7 @@ package android.location.provider {
    method public void setAllowed(boolean);
    method public void setProperties(@NonNull android.location.provider.ProviderProperties);
    field public static final String ACTION_FUSED_PROVIDER = "com.android.location.service.FusedLocationProvider";
    field public static final String ACTION_GNSS_PROVIDER = "android.location.provider.action.GNSS_PROVIDER";
    field public static final String ACTION_NETWORK_PROVIDER = "com.android.location.service.v3.NetworkLocationProvider";
  }
+15 −0
Original line number Diff line number Diff line
@@ -194,6 +194,21 @@ public class LocationManager {
     */
    public static final String GPS_PROVIDER = "gps";

    /**
     * Standard name of the GNSS hardware location provider.
     *
     * <p>This provider is similar to {@link LocationManager#GPS_PROVIDER}, but it directly uses the
     * HAL GNSS implementation and doesn't go through any provider overrides that may exist. This
     * provider will only be available when the GPS_PROVIDER is overridden with a proxy using {@link
     * android.location.provider.LocationProviderBase#ACTION_GNSS_PROVIDER}, and is intended only
     * for use internally by the location provider system.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
    public static final String GPS_HARDWARE_PROVIDER = "gps_hardware";

    /**
     * A special location provider for receiving locations without actively initiating a location
     * fix. This location provider is always present.
+0 −2
Original line number Diff line number Diff line
@@ -104,8 +104,6 @@ public abstract class LocationProviderBase {
    /**
     * The action the wrapping service should have in its intent filter to implement the
     * {@link android.location.LocationManager#GPS_PROVIDER}.
     *
     * @hide
     */
    public static final String ACTION_GNSS_PROVIDER =
            "android.location.provider.action.GNSS_PROVIDER";
+40 −13
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.location.LocationManager.BLOCK_PENDING_INTENT_SYSTEM_API_USAGE;
import static android.location.LocationManager.FUSED_PROVIDER;
import static android.location.LocationManager.GPS_HARDWARE_PROVIDER;
import static android.location.LocationManager.GPS_PROVIDER;
import static android.location.LocationManager.NETWORK_PROVIDER;
import static android.location.LocationRequest.LOW_POWER_EXCEPTIONS;
@@ -95,6 +96,7 @@ import android.util.IndentingPrintWriter;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
@@ -319,6 +321,9 @@ public class LocationManagerService extends ILocationManager.Stub implements

        for (LocationProviderManager manager : mProviderManagers) {
            if (providerName.equals(manager.getName())) {
                if (!manager.isVisibleToCaller()) {
                    return null;
                }
                return manager;
            }
        }
@@ -341,8 +346,9 @@ public class LocationManagerService extends ILocationManager.Stub implements
        }
    }

    private void addLocationProviderManager(LocationProviderManager manager,
            @Nullable AbstractLocationProvider realProvider) {
    @VisibleForTesting
    void addLocationProviderManager(
            LocationProviderManager manager, @Nullable AbstractLocationProvider realProvider) {
        synchronized (mProviderManagers) {
            Preconditions.checkState(getLocationProviderManager(manager.getName()) == null);

@@ -453,6 +459,20 @@ public class LocationManagerService extends ILocationManager.Stub implements
            }
            if (gnssProvider == null) {
                gnssProvider = mGnssManagerService.getGnssLocationProvider();
            } else {
                // If we have a GNSS provider override, add the hardware provider as a standalone
                // option for use by apps with the correct permission. Note the GNSS HAL can only
                // support a single client, so mGnssManagerService.getGnssLocationProvider() can
                // only be installed with a single provider.
                LocationProviderManager gnssHardwareManager =
                        new LocationProviderManager(
                                mContext,
                                mInjector,
                                GPS_HARDWARE_PROVIDER,
                                mPassiveManager,
                                Collections.singletonList(Manifest.permission.LOCATION_HARDWARE));
                addLocationProviderManager(
                        gnssHardwareManager, mGnssManagerService.getGnssLocationProvider());
            }

            LocationProviderManager gnssManager = new LocationProviderManager(mContext, mInjector,
@@ -629,8 +649,10 @@ public class LocationManagerService extends ILocationManager.Stub implements
    public List<String> getAllProviders() {
        ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
        for (LocationProviderManager manager : mProviderManagers) {
            if (manager.isVisibleToCaller()) {
                providers.add(manager.getName());
            }
        }
        return providers;
    }

@@ -644,16 +666,19 @@ public class LocationManagerService extends ILocationManager.Stub implements
        synchronized (mLock) {
            ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
            for (LocationProviderManager manager : mProviderManagers) {
                if (manager.isVisibleToCaller()) {
                    String name = manager.getName();
                    if (enabledOnly && !manager.isEnabled(UserHandle.getCallingUserId())) {
                        continue;
                    }
                if (criteria != null && !LocationProvider.propertiesMeetCriteria(name,
                        manager.getProperties(), criteria)) {
                    if (criteria != null
                            && !LocationProvider.propertiesMeetCriteria(
                                    name, manager.getProperties(), criteria)) {
                        continue;
                    }
                    providers.add(name);
                }
            }
            return providers;
        }
    }
@@ -1059,9 +1084,11 @@ public class LocationManagerService extends ILocationManager.Stub implements
    public void addProviderRequestListener(IProviderRequestListener listener) {
        mContext.enforceCallingOrSelfPermission(INTERACT_ACROSS_USERS, null);
        for (LocationProviderManager manager : mProviderManagers) {
            if (manager.isVisibleToCaller()) {
                manager.addProviderRequestListener(listener);
            }
        }
    }

    @Override
    public void removeProviderRequestListener(IProviderRequestListener listener) {
@@ -1649,7 +1676,7 @@ public class LocationManagerService extends ILocationManager.Stub implements
                if (provider != null && !provider.equals(manager.getName())) {
                    continue;
                }
                if (identity.equals(manager.getProviderIdentity())) {
                if (identity.equals(manager.getProviderIdentity()) && manager.isVisibleToCaller()) {
                    return true;
                }
            }
+47 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.location.provider;
import static android.app.AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION;
import static android.app.AppOpsManager.OP_MONITOR_LOCATION;
import static android.app.compat.CompatChanges.isChangeEnabled;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.location.LocationManager.DELIVER_HISTORICAL_LOCATIONS;
import static android.location.LocationManager.GPS_PROVIDER;
import static android.location.LocationManager.KEY_FLUSH_COMPLETE;
@@ -48,6 +49,7 @@ import static java.lang.Math.min;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.AlarmManager.OnAlarmListener;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
@@ -124,6 +126,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -1362,6 +1365,10 @@ public class LocationProviderManager extends
    @GuardedBy("mMultiplexerLock")
    private final ArrayList<ProviderEnabledListener> mEnabledListeners;

    // Extra permissions required to use this provider (on top of the usual location permissions).
    // Not guarded because it's read only.
    private final Collection<String> mRequiredPermissions;

    private final CopyOnWriteArrayList<IProviderRequestListener> mProviderRequestListeners;

    protected final LocationManagerInternal mLocationManagerInternal;
@@ -1435,12 +1442,34 @@ public class LocationProviderManager extends

    public LocationProviderManager(Context context, Injector injector,
            String name, @Nullable PassiveLocationProviderManager passiveManager) {
        this(context, injector, name, passiveManager, Collections.emptyList());
    }

    /**
     * Creates a manager for a location provider (the two have a 1:1 correspondence).
     *
     * @param context Context in which the manager is running.
     * @param injector Injector to retrieve system components (useful to override in testing)
     * @param name Name of this provider (used in LocationManager APIs by client apps).
     * @param passiveManager The "passive" manager (special case provider that returns locations
     *     from all other providers).
     * @param requiredPermissions Required permissions for accessing this provider. All of the given
     *     permissions are required to access the provider. If a caller doesn't hold the correct
     *     permission, the provider will be invisible to it.
     */
    public LocationProviderManager(
            Context context,
            Injector injector,
            String name,
            @Nullable PassiveLocationProviderManager passiveManager,
            Collection<String> requiredPermissions) {
        mContext = context;
        mName = Objects.requireNonNull(name);
        mPassiveManager = passiveManager;
        mState = STATE_STOPPED;
        mEnabled = new SparseBooleanArray(2);
        mLastLocations = new SparseArray<>(2);
        mRequiredPermissions = requiredPermissions;

        mEnabledListeners = new ArrayList<>();
        mProviderRequestListeners = new CopyOnWriteArrayList<>();
@@ -1559,6 +1588,24 @@ public class LocationProviderManager extends
        }
    }

    /**
     * Returns true if this provider is visible to the current caller (whether called from a binder
     * thread or not). If a provider isn't visible, then all APIs return the same data they would if
     * the provider didn't exist (i.e. the caller can't see or use the provider).
     *
     * <p>This method doesn't require any permissions, but uses permissions to determine which
     * subset of providers are visible.
     */
    @SuppressLint("AndroidFrameworkRequiresPermission")
    public boolean isVisibleToCaller() {
        for (String permission : mRequiredPermissions) {
            if (mContext.checkCallingOrSelfPermission(permission) != PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    public void addEnabledListener(ProviderEnabledListener listener) {
        synchronized (mMultiplexerLock) {
            Preconditions.checkState(mState != STATE_STOPPED);
Loading