Switches ADAS allowlist away from string resources

Bug: 226440115
Test: manually

Change-Id: I3d1434c405a1babee999533afa10710a06f635a1
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index db41d33..1feb5d4 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -88,8 +88,8 @@
     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 @@
     // without throttling, as read from the configuration files.
     final ArraySet<String> 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<String, ArraySet<String>> 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<String, ArraySet<String>> mAllowIgnoreLocationSettings = new ArrayMap<>();
@@ -394,6 +398,10 @@
         return mAllowUnthrottledLocation;
     }
 
+    public ArrayMap<String, ArraySet<String>> getAllowAdasLocationSettings() {
+        return mAllowAdasSettings;
+    }
+
     public ArrayMap<String, ArraySet<String>> getAllowIgnoreLocationSettings() {
         return mAllowIgnoreLocationSettings;
     }
@@ -1007,6 +1015,34 @@
                         }
                         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<String> 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 c55eed9..7d22681 100644
--- a/location/java/android/location/LocationDeviceConfig.java
+++ b/location/java/android/location/LocationDeviceConfig.java
@@ -24,6 +24,30 @@
 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.
+     *
+     * <p>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.
+     *
+     * <p>Examples of valid entries:
+     *
+     * <ul>
+     *   <li>android
+     *   <li>android;*
+     *   <li>android;*,com.example.app;null;my_attr
+     *   <li>android;*,com.example.app;null;my_attr,com.example.otherapp;my_attr
+     * </ul>
+     */
+    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
      * emergency purposes only.
@@ -39,10 +63,10 @@
      * <p>Examples of valid entries:
      *
      * <ul>
-     *     <li>android</li>
-     *     <li>android;*</li>
-     *     <li>android;*,com.example.app;null;my_attr</li>
-     *     <li>android;*,com.example.app;null;my_attr,com.example.otherapp;my_attr</li>
+     *   <li>android
+     *   <li>android;*
+     *   <li>android;*,com.example.app;null;my_attr
+     *   <li>android;*,com.example.app;null;my_attr,com.example.otherapp;my_attr
      * </ul>
      */
     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 fac5106..31d5136 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.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 @@
                 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 @@
                 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 @@
                 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 @@
                 }
             }
             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 148afa7..490bfe1 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 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 3e8da7d..777683e 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 @@
     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 @@
                 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());
@@ -233,6 +238,21 @@
     }
 
     @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 @@
 
         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 721ef1e..1235352 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 @@
                 } 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 @@
             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 @@
             } 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 @@
                 mBackgroundThrottlePackageWhitelistChangedListener);
         mSettingsHelper.addOnLocationPackageBlacklistChangedListener(
                 mLocationPackageBlacklistChangedListener);
+        mSettingsHelper.addAdasAllowlistChangedListener(
+                mAdasPackageAllowlistChangedListener);
         mSettingsHelper.addIgnoreSettingsAllowlistChangedListener(
                 mIgnoreSettingsPackageWhitelistChangedListener);
         mLocationPermissionsHelper.addListener(mLocationPermissionsListener);
@@ -2000,6 +2010,7 @@
                 mBackgroundThrottlePackageWhitelistChangedListener);
         mSettingsHelper.removeOnLocationPackageBlacklistChangedListener(
                 mLocationPackageBlacklistChangedListener);
+        mSettingsHelper.removeAdasAllowlistChangedListener(mAdasPackageAllowlistChangedListener);
         mSettingsHelper.removeIgnoreSettingsAllowlistChangedListener(
                 mIgnoreSettingsPackageWhitelistChangedListener);
         mLocationPermissionsHelper.removeListener(mLocationPermissionsListener);
@@ -2422,6 +2433,12 @@
         }
     }
 
+    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 cd70020..b76abe6 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 @@
     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(
@@ -194,10 +196,29 @@
     }
 
     @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 d8f409d..71cc65b 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 @@
         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 @@
         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 @@
 
     @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);