Loading core/api/system-current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -6252,6 +6252,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 { Loading Loading @@ -6391,6 +6392,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"; } location/java/android/location/LocationManager.java +15 −0 Original line number Diff line number Diff line Loading @@ -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. Loading location/java/android/location/provider/LocationProviderBase.java +0 −2 Original line number Diff line number Diff line Loading @@ -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"; Loading services/core/java/com/android/server/location/LocationManagerService.java +40 −13 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; } } Loading @@ -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); Loading Loading @@ -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, Loading Loading @@ -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; } Loading @@ -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; } } Loading Loading @@ -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) { Loading Loading @@ -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; } } Loading services/core/java/com/android/server/location/provider/LocationProviderManager.java +47 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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<>(); Loading Loading @@ -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 Loading
core/api/system-current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -6252,6 +6252,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 { Loading Loading @@ -6391,6 +6392,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"; }
location/java/android/location/LocationManager.java +15 −0 Original line number Diff line number Diff line Loading @@ -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. Loading
location/java/android/location/provider/LocationProviderBase.java +0 −2 Original line number Diff line number Diff line Loading @@ -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"; Loading
services/core/java/com/android/server/location/LocationManagerService.java +40 −13 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; } } Loading @@ -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); Loading Loading @@ -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, Loading Loading @@ -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; } Loading @@ -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; } } Loading Loading @@ -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) { Loading Loading @@ -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; } } Loading
services/core/java/com/android/server/location/provider/LocationProviderManager.java +47 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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<>(); Loading Loading @@ -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