diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index db41d333e1d44..1feb5d415e168 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -88,8 +88,8 @@ public class SystemConfig { private static final int ALLOW_HIDDENAPI_WHITELISTING = 0x040; private static final int ALLOW_ASSOCIATIONS = 0x080; // ALLOW_OVERRIDE_APP_RESTRICTIONS allows to use "allow-in-power-save-except-idle", - // "allow-in-power-save", "allow-in-data-usage-save", "allow-unthrottled-location", - // and "allow-ignore-location-settings". + // "allow-in-power-save", "allow-in-data-usage-save","allow-unthrottled-location", + // "allow-ignore-location-settings" and "allow-adas-location-settings". private static final int ALLOW_OVERRIDE_APP_RESTRICTIONS = 0x100; private static final int ALLOW_IMPLICIT_BROADCASTS = 0x200; private static final int ALLOW_VENDOR_APEX = 0x400; @@ -234,6 +234,10 @@ public class SystemConfig { // without throttling, as read from the configuration files. final ArraySet mAllowUnthrottledLocation = new ArraySet<>(); + // These are the packages that are allow-listed to be able to retrieve location when + // the location state is driver assistance only. + final ArrayMap> mAllowAdasSettings = new ArrayMap<>(); + // These are the packages that are white-listed to be able to retrieve location even when user // location settings are off, for emergency purposes, as read from the configuration files. final ArrayMap> mAllowIgnoreLocationSettings = new ArrayMap<>(); @@ -394,6 +398,10 @@ public class SystemConfig { return mAllowUnthrottledLocation; } + public ArrayMap> getAllowAdasLocationSettings() { + return mAllowAdasSettings; + } + public ArrayMap> getAllowIgnoreLocationSettings() { return mAllowIgnoreLocationSettings; } @@ -1007,6 +1015,34 @@ public class SystemConfig { } XmlUtils.skipCurrentTag(parser); } break; + case "allow-adas-location-settings" : { + if (allowOverrideAppRestrictions) { + String pkgname = parser.getAttributeValue(null, "package"); + String attributionTag = parser.getAttributeValue(null, + "attributionTag"); + if (pkgname == null) { + Slog.w(TAG, "<" + name + "> without package in " + + permFile + " at " + parser.getPositionDescription()); + } else { + ArraySet tags = mAllowAdasSettings.get(pkgname); + if (tags == null || !tags.isEmpty()) { + if (tags == null) { + tags = new ArraySet<>(1); + mAllowAdasSettings.put(pkgname, tags); + } + if (!"*".equals(attributionTag)) { + if ("null".equals(attributionTag)) { + attributionTag = null; + } + tags.add(attributionTag); + } + } + } + } else { + logNotAllowedInPartition(name, permFile, parser); + } + XmlUtils.skipCurrentTag(parser); + } break; case "allow-ignore-location-settings": { if (allowOverrideAppRestrictions) { String pkgname = parser.getAttributeValue(null, "package"); diff --git a/location/java/android/location/LocationDeviceConfig.java b/location/java/android/location/LocationDeviceConfig.java index c55eed9211f7e..7d22681fc93e4 100644 --- a/location/java/android/location/LocationDeviceConfig.java +++ b/location/java/android/location/LocationDeviceConfig.java @@ -23,6 +23,30 @@ package android.location; */ public final class LocationDeviceConfig { + /** + * Package/tag combinations that are allowlisted for ignoring location settings (may retrieve + * location even when user location settings are off), for advanced driver-assistance systems + * only. + * + *

Package/tag combinations are separated by commas (","), and with in each combination is a + * package name followed by 0 or more attribution tags, separated by semicolons (";"). If a + * package is followed by 0 attribution tags, this is interpreted the same as the wildcard + * value. There are two special interpreted values for attribution tags, the wildcard value + * ("*") which represents all attribution tags, and the null value ("null"), which is converted + * to the null string (since attribution tags may be null). This format implies that attribution + * tags which should be on this list may not contain semicolons. + * + *

Examples of valid entries: + * + *

    + *
  • android + *
  • android;* + *
  • android;*,com.example.app;null;my_attr + *
  • android;*,com.example.app;null;my_attr,com.example.otherapp;my_attr + *
+ */ + public static final String ADAS_SETTINGS_ALLOWLIST = "adas_settings_allowlist"; + /** * Package/tag combinations that are allowedlisted for ignoring location settings (may retrieve * location even when user location settings are off, and may ignore throttling, etc), for @@ -39,10 +63,10 @@ public final class LocationDeviceConfig { *

Examples of valid entries: * *

    - *
  • android
  • - *
  • android;*
  • - *
  • android;*,com.example.app;null;my_attr
  • - *
  • android;*,com.example.app;null;my_attr,com.example.otherapp;my_attr
  • + *
  • android + *
  • android;* + *
  • android;*,com.example.app;null;my_attr + *
  • android;*,com.example.app;null;my_attr,com.example.otherapp;my_attr *
*/ public static final String IGNORE_SETTINGS_ALLOWLIST = "ignore_settings_allowlist"; diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java index fac5106518789..31d5136c80a53 100644 --- a/services/core/java/com/android/server/location/LocationManagerService.java +++ b/services/core/java/com/android/server/location/LocationManagerService.java @@ -94,7 +94,6 @@ import android.util.IndentingPrintWriter; import android.util.Log; import com.android.internal.annotations.GuardedBy; -import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.Preconditions; import com.android.server.FgThread; @@ -279,6 +278,9 @@ public class LocationManagerService extends ILocationManager.Stub implements this::onLocationUserSettingsChanged); mInjector.getSettingsHelper().addOnLocationEnabledChangedListener( this::onLocationModeChanged); + mInjector.getSettingsHelper().addAdasAllowlistChangedListener( + () -> refreshAppOpsRestrictions(UserHandle.USER_ALL) + ); mInjector.getSettingsHelper().addIgnoreSettingsAllowlistChangedListener( () -> refreshAppOpsRestrictions(UserHandle.USER_ALL)); mInjector.getUserInfoHelper().addListener((userId, change) -> { @@ -823,12 +825,6 @@ public class LocationManagerService extends ILocationManager.Stub implements throw new IllegalArgumentException( "adas gnss bypass requests are only allowed on the \"gps\" provider"); } - if (!ArrayUtils.contains(mContext.getResources().getStringArray( - com.android.internal.R.array.config_locationDriverAssistancePackageNames), - identity.getPackageName())) { - throw new SecurityException( - "only verified adas packages may use adas gnss bypass requests"); - } if (!isLocationProvider) { LocationPermissions.enforceCallingOrSelfBypassPermission(mContext); } @@ -923,12 +919,6 @@ public class LocationManagerService extends ILocationManager.Stub implements throw new IllegalArgumentException( "adas gnss bypass requests are only allowed on the \"gps\" provider"); } - if (!ArrayUtils.contains(mContext.getResources().getStringArray( - com.android.internal.R.array.config_locationDriverAssistancePackageNames), - identity.getPackageName())) { - throw new SecurityException( - "only verified adas packages may use adas gnss bypass requests"); - } if (!isLocationProvider) { LocationPermissions.enforceCallingOrSelfBypassPermission(mContext); } @@ -1542,6 +1532,7 @@ public class LocationManagerService extends ILocationManager.Stub implements } } builder.add(mInjector.getSettingsHelper().getIgnoreSettingsAllowlist()); + builder.add(mInjector.getSettingsHelper().getAdasAllowlist()); allowedPackages = builder.build(); } diff --git a/services/core/java/com/android/server/location/injector/SettingsHelper.java b/services/core/java/com/android/server/location/injector/SettingsHelper.java index 148afa75ca751..490bfe1ab82fd 100644 --- a/services/core/java/com/android/server/location/injector/SettingsHelper.java +++ b/services/core/java/com/android/server/location/injector/SettingsHelper.java @@ -146,6 +146,20 @@ public abstract class SettingsHelper { public abstract void removeOnGnssMeasurementsFullTrackingEnabledChangedListener( GlobalSettingChangedListener listener); + /** Retrieve adas allowlist. */ + public abstract PackageTagsList getAdasAllowlist(); + + /** + * Add a listener for changes to the ADAS settings package allowlist. Callbacks occur on an + * unspecified thread. + */ + public abstract void addAdasAllowlistChangedListener(GlobalSettingChangedListener listener); + + /** + * Remove a listener for changes to the ADAS package allowlist. + */ + public abstract void removeAdasAllowlistChangedListener(GlobalSettingChangedListener listener); + /** * Retrieve the ignore location settings package+tags allowlist setting. */ diff --git a/services/core/java/com/android/server/location/injector/SystemSettingsHelper.java b/services/core/java/com/android/server/location/injector/SystemSettingsHelper.java index 3e8da7d7478ab..777683ef59cfe 100644 --- a/services/core/java/com/android/server/location/injector/SystemSettingsHelper.java +++ b/services/core/java/com/android/server/location/injector/SystemSettingsHelper.java @@ -16,6 +16,7 @@ package com.android.server.location.injector; +import static android.location.LocationDeviceConfig.ADAS_SETTINGS_ALLOWLIST; import static android.location.LocationDeviceConfig.IGNORE_SETTINGS_ALLOWLIST; import static android.provider.Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING; import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS; @@ -80,6 +81,7 @@ public class SystemSettingsHelper extends SettingsHelper { private final StringListCachedSecureSetting mLocationPackageBlacklist; private final StringListCachedSecureSetting mLocationPackageWhitelist; private final StringSetCachedGlobalSetting mBackgroundThrottlePackageWhitelist; + private final PackageTagsListSetting mAdasPackageAllowlist; private final PackageTagsListSetting mIgnoreSettingsPackageAllowlist; public SystemSettingsHelper(Context context) { @@ -98,6 +100,9 @@ public class SystemSettingsHelper extends SettingsHelper { LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST, () -> SystemConfig.getInstance().getAllowUnthrottledLocation(), FgThread.getHandler()); + mAdasPackageAllowlist = new PackageTagsListSetting( + ADAS_SETTINGS_ALLOWLIST, + () -> SystemConfig.getInstance().getAllowAdasLocationSettings()); mIgnoreSettingsPackageAllowlist = new PackageTagsListSetting( IGNORE_SETTINGS_ALLOWLIST, () -> SystemConfig.getInstance().getAllowIgnoreLocationSettings()); @@ -232,6 +237,21 @@ public class SystemSettingsHelper extends SettingsHelper { mGnssMeasurementFullTracking.removeListener(listener); } + @Override + public PackageTagsList getAdasAllowlist() { + return mAdasPackageAllowlist.getValue(); + } + + @Override + public void addAdasAllowlistChangedListener(GlobalSettingChangedListener listener) { + mAdasPackageAllowlist.addListener(listener); + } + + @Override + public void removeAdasAllowlistChangedListener(GlobalSettingChangedListener listener) { + mAdasPackageAllowlist.removeListener(listener); + } + @Override public PackageTagsList getIgnoreSettingsAllowlist() { return mIgnoreSettingsPackageAllowlist.getValue(); @@ -359,11 +379,19 @@ public class SystemSettingsHelper extends SettingsHelper { PackageTagsList ignoreSettingsAllowlist = mIgnoreSettingsPackageAllowlist.getValue(); if (!ignoreSettingsAllowlist.isEmpty()) { - ipw.println("Bypass Allow Packages:"); + ipw.println("Emergency Bypass Allow Packages:"); ipw.increaseIndent(); ignoreSettingsAllowlist.dump(ipw); ipw.decreaseIndent(); } + + PackageTagsList adasPackageAllowlist = mAdasPackageAllowlist.getValue(); + if (!adasPackageAllowlist.isEmpty()) { + ipw.println("ADAS Bypass Allow Packages:"); + ipw.increaseIndent(); + adasPackageAllowlist.dump(ipw); + ipw.decreaseIndent(); + } } private abstract static class ObservingSetting extends ContentObserver { diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java index 721ef1ed358f4..1235352b0590f 100644 --- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java +++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java @@ -699,6 +699,9 @@ public class LocationProviderManager extends } else if (!mLocationSettings.getUserSettings( getIdentity().getUserId()).isAdasGnssLocationEnabled()) { adasGnssBypass = false; + } else if (!mSettingsHelper.getAdasAllowlist().contains( + getIdentity().getPackageName(), getIdentity().getAttributionTag())) { + adasGnssBypass = false; } builder.setAdasGnssBypass(adasGnssBypass); @@ -1406,6 +1409,8 @@ public class LocationProviderManager extends this::onAppForegroundChanged; private final GlobalSettingChangedListener mBackgroundThrottleIntervalChangedListener = this::onBackgroundThrottleIntervalChanged; + private final GlobalSettingChangedListener mAdasPackageAllowlistChangedListener = + this::onAdasAllowlistChanged; private final GlobalSettingChangedListener mIgnoreSettingsPackageWhitelistChangedListener = this::onIgnoreSettingsWhitelistChanged; private final LocationPowerSaveModeChangedListener mLocationPowerSaveModeChangedListener = @@ -1710,6 +1715,9 @@ public class LocationProviderManager extends } else if (!mLocationSettings.getUserSettings( identity.getUserId()).isAdasGnssLocationEnabled()) { adasGnssBypass = false; + } else if (!mSettingsHelper.getAdasAllowlist().contains( + identity.getPackageName(), identity.getAttributionTag())) { + adasGnssBypass = false; } builder.setAdasGnssBypass(adasGnssBypass); @@ -1979,6 +1987,8 @@ public class LocationProviderManager extends mBackgroundThrottlePackageWhitelistChangedListener); mSettingsHelper.addOnLocationPackageBlacklistChangedListener( mLocationPackageBlacklistChangedListener); + mSettingsHelper.addAdasAllowlistChangedListener( + mAdasPackageAllowlistChangedListener); mSettingsHelper.addIgnoreSettingsAllowlistChangedListener( mIgnoreSettingsPackageWhitelistChangedListener); mLocationPermissionsHelper.addListener(mLocationPermissionsListener); @@ -2000,6 +2010,7 @@ public class LocationProviderManager extends mBackgroundThrottlePackageWhitelistChangedListener); mSettingsHelper.removeOnLocationPackageBlacklistChangedListener( mLocationPackageBlacklistChangedListener); + mSettingsHelper.removeAdasAllowlistChangedListener(mAdasPackageAllowlistChangedListener); mSettingsHelper.removeIgnoreSettingsAllowlistChangedListener( mIgnoreSettingsPackageWhitelistChangedListener); mLocationPermissionsHelper.removeListener(mLocationPermissionsListener); @@ -2422,6 +2433,12 @@ public class LocationProviderManager extends } } + private void onAdasAllowlistChanged() { + synchronized (mLock) { + updateRegistrations(Registration::onProviderLocationRequestChanged); + } + } + private void onIgnoreSettingsWhitelistChanged() { synchronized (mLock) { updateRegistrations(Registration::onProviderLocationRequestChanged); diff --git a/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeSettingsHelper.java b/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeSettingsHelper.java index cd70020f5c287..b76abe6c74aa5 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeSettingsHelper.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeSettingsHelper.java @@ -84,6 +84,8 @@ public class FakeSettingsHelper extends SettingsHelper { private final Setting mBackgroundThrottlePackageWhitelistSetting = new Setting( Collections.emptySet()); private final Setting mGnssMeasurementsFullTrackingSetting = new Setting(Boolean.FALSE); + private final Setting mAdasPackageAllowlist = new Setting( + new PackageTagsList.Builder().build()); private final Setting mIgnoreSettingsAllowlist = new Setting( new PackageTagsList.Builder().build()); private final Setting mBackgroundThrottleProximityAlertIntervalSetting = new Setting( @@ -193,11 +195,30 @@ public class FakeSettingsHelper extends SettingsHelper { mGnssMeasurementsFullTrackingSetting.removeListener(listener); } + @Override + public PackageTagsList getAdasAllowlist() { + return mAdasPackageAllowlist.getValue(PackageTagsList.class); + } + + @Override + public void addAdasAllowlistChangedListener(GlobalSettingChangedListener listener) { + mAdasPackageAllowlist.addListener(listener); + } + + @Override + public void removeAdasAllowlistChangedListener(GlobalSettingChangedListener listener) { + mAdasPackageAllowlist.removeListener(listener); + } + @Override public PackageTagsList getIgnoreSettingsAllowlist() { return mIgnoreSettingsAllowlist.getValue(PackageTagsList.class); } + public void setAdasSettingsAllowlist(PackageTagsList newValue) { + mAdasPackageAllowlist.setValue(newValue); + } + public void setIgnoreSettingsAllowlist(PackageTagsList newValue) { mIgnoreSettingsAllowlist.setValue(newValue); } diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java index d8f409dfce66a..71cc65b484ee1 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java @@ -1107,6 +1107,10 @@ public class LocationProviderManagerTest { doReturn(true).when(mPackageManager).hasSystemFeature(FEATURE_AUTOMOTIVE); doReturn(true).when(mResources).getBoolean(R.bool.config_defaultAdasGnssLocationEnabled); + mInjector.getSettingsHelper().setAdasSettingsAllowlist( + new PackageTagsList.Builder().add( + IDENTITY.getPackageName()).build()); + createManager(GPS_PROVIDER); ILocationListener listener1 = createMockLocationListener(); @@ -1136,6 +1140,10 @@ public class LocationProviderManagerTest { doReturn(true).when(mPackageManager).hasSystemFeature(FEATURE_AUTOMOTIVE); doReturn(true).when(mResources).getBoolean(R.bool.config_defaultAdasGnssLocationEnabled); + mInjector.getSettingsHelper().setAdasSettingsAllowlist( + new PackageTagsList.Builder().add( + IDENTITY.getPackageName()).build()); + createManager(GPS_PROVIDER); ILocationListener listener1 = createMockLocationListener(); @@ -1160,11 +1168,16 @@ public class LocationProviderManagerTest { @Test public void testProviderRequest_AdasGnssBypass_ProviderDisabled_AdasDisabled() { + doReturn(true).when(mPackageManager).hasSystemFeature(FEATURE_AUTOMOTIVE); + doReturn(true).when(mResources).getBoolean(R.bool.config_defaultAdasGnssLocationEnabled); + mInjector.getSettingsHelper().setIgnoreSettingsAllowlist( new PackageTagsList.Builder().add( IDENTITY.getPackageName()).build()); - doReturn(true).when(mPackageManager).hasSystemFeature(FEATURE_AUTOMOTIVE); - doReturn(true).when(mResources).getBoolean(R.bool.config_defaultAdasGnssLocationEnabled); + + mInjector.getSettingsHelper().setAdasSettingsAllowlist( + new PackageTagsList.Builder().add( + IDENTITY.getPackageName()).build()); createManager(GPS_PROVIDER);