Update location bypass allowlist

Create a new DeviceConfig entry to replace the prior Settings entry on
which the location ignore settings allowlist is based. This allows us to
allowlist based on attribution tag, and eliminate holes for large
applications.

Test: manual + CTS + GTS
Bug: 187421886
Change-Id: I31e61db79b93e202bd8c66efae1bb5aaf0c88ff5
This commit is contained in:
Soonil Nagarkar
2021-05-20 18:28:55 -07:00
parent f0ec6471cc
commit 1ea818347e
25 changed files with 814 additions and 206 deletions

View File

@@ -4930,6 +4930,10 @@ package android.location {
field @Deprecated public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
}
public final class LocationDeviceConfig {
field public static final String IGNORE_SETTINGS_ALLOWLIST = "ignore_settings_allowlist";
}
public class LocationManager {
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void addProviderRequestChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.ChangedListener);
method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
@@ -9088,6 +9092,7 @@ package android.provider {
field public static final String NAMESPACE_GAME_DRIVER = "game_driver";
field public static final String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot";
field public static final String NAMESPACE_INTELLIGENCE_ATTENTION = "intelligence_attention";
field public static final String NAMESPACE_LOCATION = "location";
field public static final String NAMESPACE_MEDIA = "media";
field public static final String NAMESPACE_MEDIA_NATIVE = "media_native";
field public static final String NAMESPACE_NETD_NATIVE = "netd_native";

View File

@@ -1356,9 +1356,14 @@ package android.location {
method public void setType(int);
}
public final class LocationDeviceConfig {
field public static final String IGNORE_SETTINGS_ALLOWLIST = "ignore_settings_allowlist";
}
public class LocationManager {
method @NonNull public String[] getBackgroundThrottlingWhitelist();
method @NonNull public String[] getIgnoreSettingsWhitelist();
method @NonNull public android.os.PackageTagsList getIgnoreSettingsAllowlist();
method @Deprecated @NonNull public String[] getIgnoreSettingsWhitelist();
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
}
@@ -1653,6 +1658,28 @@ package android.os {
method public void removeSyncBarrier(int);
}
public final class PackageTagsList implements android.os.Parcelable {
method public boolean contains(@NonNull String, @Nullable String);
method public boolean contains(@NonNull android.os.PackageTagsList);
method public boolean containsAll(@NonNull String);
method public int describeContents();
method public boolean includes(@NonNull String);
method public boolean isEmpty();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.os.PackageTagsList> CREATOR;
}
public static final class PackageTagsList.Builder {
ctor public PackageTagsList.Builder();
ctor public PackageTagsList.Builder(int);
method @NonNull public android.os.PackageTagsList.Builder add(@NonNull String);
method @NonNull public android.os.PackageTagsList.Builder add(@NonNull String, @Nullable String);
method @NonNull public android.os.PackageTagsList.Builder add(@NonNull android.os.PackageTagsList);
method @NonNull public android.os.PackageTagsList.Builder add(@NonNull java.util.Map<java.lang.String,? extends java.util.Set<java.lang.String>>);
method @NonNull public android.os.PackageTagsList build();
method @NonNull public android.os.PackageTagsList.Builder clear();
}
public final class Parcel {
method public boolean allowSquashing();
method public int readExceptionCode();
@@ -2087,7 +2114,7 @@ package android.provider {
field public static final String HIDDEN_API_BLACKLIST_EXEMPTIONS = "hidden_api_blacklist_exemptions";
field public static final String HIDDEN_API_POLICY = "hidden_api_policy";
field public static final String HIDE_ERROR_DIALOGS = "hide_error_dialogs";
field public static final String LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST = "location_ignore_settings_package_whitelist";
field @Deprecated public static final String LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST = "location_ignore_settings_package_whitelist";
field public static final String LOW_POWER_MODE = "low_power";
field public static final String LOW_POWER_MODE_STICKY = "low_power_sticky";
field @Deprecated public static final String NOTIFICATION_BUBBLES = "notification_bubbles";

View File

@@ -49,6 +49,7 @@ import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.PackageTagsList;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
@@ -7407,7 +7408,7 @@ public class AppOpsManager {
/** @hide */
public void setUserRestriction(int code, boolean restricted, IBinder token) {
setUserRestriction(code, restricted, token, (Map<String, String[]>) null);
setUserRestriction(code, restricted, token, null);
}
/**
@@ -7415,7 +7416,7 @@ public class AppOpsManager {
* @hide
*/
public void setUserRestriction(int code, boolean restricted, IBinder token,
@Nullable Map<String, String[]> excludedPackageTags) {
@Nullable PackageTagsList excludedPackageTags) {
setUserRestrictionForUser(code, restricted, token, excludedPackageTags,
mContext.getUserId());
}
@@ -7425,7 +7426,7 @@ public class AppOpsManager {
* @hide
*/
public void setUserRestrictionForUser(int code, boolean restricted, IBinder token,
@Nullable Map<String, String[]> excludedPackageTags, int userId) {
@Nullable PackageTagsList excludedPackageTags, int userId) {
try {
mService.setUserRestriction(code, restricted, token, userId, excludedPackageTags);
} catch (RemoteException e) {

View File

@@ -0,0 +1,18 @@
/* Copyright 2018, 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 android.os;
parcelable PackageTagsList;

View File

@@ -0,0 +1,310 @@
/*
* Copyright (C) 2021 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 android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.util.ArrayMap;
import android.util.ArraySet;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* A list of packages and associated attribution tags that supports easy membership checks.
*
* @hide
*/
@TestApi
public final class PackageTagsList implements Parcelable {
// an empty set value matches any attribution tag
private final ArrayMap<String, ArraySet<String>> mPackageTags;
private PackageTagsList(@NonNull ArrayMap<String, ArraySet<String>> packageTags) {
mPackageTags = Objects.requireNonNull(packageTags);
}
/**
* Returns true if this instance is empty;
*/
public boolean isEmpty() {
return mPackageTags.isEmpty();
}
/**
* Returns true if the given package is represented within this instance. If this returns true
* this does not imply anything about whether any given attribution tag under the given package
* name is present.
*/
public boolean includes(@NonNull String packageName) {
return mPackageTags.containsKey(packageName);
}
/**
* Returns true if all attribution tags under the given package are contained within this
* instance.
*/
public boolean containsAll(@NonNull String packageName) {
Set<String> tags = mPackageTags.get(packageName);
return tags != null && tags.isEmpty();
}
/**
* Returns true if the given package and attribution tag are contained within this instance.
*/
public boolean contains(@NonNull String packageName, @Nullable String attributionTag) {
Set<String> tags = mPackageTags.get(packageName);
if (tags == null) {
return false;
} else if (tags.isEmpty()) {
return true;
} else {
return tags.contains(attributionTag);
}
}
/**
* Returns true if the given PackageTagsList is a subset of this instance.
*/
public boolean contains(@NonNull PackageTagsList packageTagsList) {
int otherSize = packageTagsList.mPackageTags.size();
if (otherSize > mPackageTags.size()) {
return false;
}
for (int i = 0; i < otherSize; i++) {
String packageName = packageTagsList.mPackageTags.keyAt(i);
ArraySet<String> tags = mPackageTags.get(packageName);
if (tags == null) {
return false;
}
if (tags.isEmpty()) {
continue;
}
ArraySet<String> otherTags = packageTagsList.mPackageTags.valueAt(i);
if (otherTags.isEmpty()) {
return false;
}
if (!tags.containsAll(otherTags)) {
return false;
}
}
return true;
}
public static final @NonNull Parcelable.Creator<PackageTagsList> CREATOR =
new Parcelable.Creator<PackageTagsList>() {
@SuppressWarnings("unchecked")
@Override
public PackageTagsList createFromParcel(Parcel in) {
int count = in.readInt();
ArrayMap<String, ArraySet<String>> packageTags = new ArrayMap<>(count);
for (int i = 0; i < count; i++) {
String key = in.readString8();
ArraySet<String> value = (ArraySet<String>) in.readArraySet(null);
packageTags.append(key, value);
}
return new PackageTagsList(packageTags);
}
@Override
public PackageTagsList[] newArray(int size) {
return new PackageTagsList[size];
}
};
@Override
public void writeToParcel(@NonNull Parcel parcel, int flags) {
int count = mPackageTags.size();
parcel.writeInt(count);
for (int i = 0; i < count; i++) {
parcel.writeString8(mPackageTags.keyAt(i));
parcel.writeArraySet(mPackageTags.valueAt(i));
}
}
@Override
public int describeContents() {
return 0;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof PackageTagsList)) {
return false;
}
PackageTagsList that = (PackageTagsList) o;
return mPackageTags.equals(that.mPackageTags);
}
@Override
public int hashCode() {
return Objects.hash(mPackageTags);
}
@Override
public @NonNull String toString() {
return mPackageTags.toString();
}
/**
* @hide
*/
public void dump(PrintWriter pw) {
int size = mPackageTags.size();
for (int i = 0; i < size; i++) {
String packageName = mPackageTags.keyAt(i);
pw.print(packageName);
pw.print("[");
int tagsSize = mPackageTags.valueAt(i).size();
if (tagsSize == 0) {
pw.print("*");
} else {
for (int j = 0; j < tagsSize; j++) {
String attributionTag = mPackageTags.valueAt(i).valueAt(j);
if (j > 0) {
pw.print(", ");
}
if (attributionTag.startsWith(packageName)) {
pw.print(attributionTag.substring(packageName.length()));
} else {
pw.print(attributionTag);
}
}
}
pw.println("]");
}
}
/**
* Builder class for {@link PackageTagsList}.
*/
public static final class Builder {
private final ArrayMap<String, ArraySet<String>> mPackageTags;
/**
* Creates a new builder.
*/
public Builder() {
mPackageTags = new ArrayMap<>();
}
/**
* Creates a new builder with the given initial capacity.
*/
public Builder(int capacity) {
mPackageTags = new ArrayMap<>(capacity);
}
/**
* Adds all attribution tags under the specified package to the builder.
*/
@SuppressLint("MissingGetterMatchingBuilder")
public @NonNull Builder add(@NonNull String packageName) {
mPackageTags.computeIfAbsent(packageName, p -> new ArraySet<>()).clear();
return this;
}
/**
* Adds the specified package and attribution tag to the builder.
*/
@SuppressLint("MissingGetterMatchingBuilder")
public @NonNull Builder add(@NonNull String packageName, @Nullable String attributionTag) {
ArraySet<String> tags = mPackageTags.get(packageName);
if (tags == null) {
tags = new ArraySet<>(1);
tags.add(attributionTag);
mPackageTags.put(packageName, tags);
} else if (!tags.isEmpty()) {
tags.add(attributionTag);
}
return this;
}
/**
* Adds the specified {@link PackageTagsList} to the builder.
*/
@SuppressLint("MissingGetterMatchingBuilder")
public @NonNull Builder add(@NonNull PackageTagsList packageTagsList) {
return add(packageTagsList.mPackageTags);
}
/**
* Adds the given map of package to attribution tags to the builder. An empty set of
* attribution tags is interpreted to imply all attribution tags under that package.
*/
@SuppressLint("MissingGetterMatchingBuilder")
public @NonNull Builder add(@NonNull Map<String, ? extends Set<String>> packageTagsMap) {
mPackageTags.ensureCapacity(packageTagsMap.size());
for (Map.Entry<String, ? extends Set<String>> entry : packageTagsMap.entrySet()) {
Set<String> newTags = entry.getValue();
if (newTags.isEmpty()) {
add(entry.getKey());
} else {
ArraySet<String> tags = mPackageTags.get(entry.getKey());
if (tags == null) {
tags = new ArraySet<>(newTags);
mPackageTags.put(entry.getKey(), tags);
} else if (!tags.isEmpty()) {
tags.addAll(newTags);
}
}
}
return this;
}
/**
* Clears the builder.
*/
public @NonNull Builder clear() {
mPackageTags.clear();
return this;
}
/**
* Constructs a new {@link PackageTagsList}.
*/
public @NonNull PackageTagsList build() {
return new PackageTagsList(copy(mPackageTags));
}
private static ArrayMap<String, ArraySet<String>> copy(
ArrayMap<String, ArraySet<String>> value) {
int size = value.size();
ArrayMap<String, ArraySet<String>> copy = new ArrayMap<>(size);
for (int i = 0; i < size; i++) {
String packageName = value.keyAt(i);
ArraySet<String> tags = new ArraySet<>(Objects.requireNonNull(value.valueAt(i)));
copy.append(packageName, tags);
}
return copy;
}
}
}

View File

@@ -257,6 +257,14 @@ public final class DeviceConfig {
@TestApi
public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler";
/**
* Namespace for all location related features.
*
* @hide
*/
@SystemApi
public static final String NAMESPACE_LOCATION = "location";
/**
* Namespace for all media related features.
*

View File

@@ -10988,10 +10988,12 @@ public final class Settings {
/**
* Packages that are whitelisted for ignoring location settings (may retrieve location even
* when user location settings are off), for emergency purposes.
* @deprecated No longer used from Android 12+
* @hide
*/
@TestApi
@Readable
@Deprecated
public static final String LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST =
"location_ignore_settings_package_whitelist";

View File

@@ -23,6 +23,7 @@ import android.app.RuntimeAppOpAccessMessage;
import android.content.AttributionSource;
import android.content.pm.ParceledListSlice;
import android.os.Bundle;
import android.os.PackageTagsList;
import android.os.RemoteCallback;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsActiveCallback;
@@ -92,7 +93,7 @@ interface IAppOpsService {
void setAudioRestriction(int code, int usage, int uid, int mode, in String[] exceptionPackages);
void setUserRestrictions(in Bundle restrictions, IBinder token, int userHandle);
void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle, in Map<String, String[]> excludedPackageTags);
void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle, in PackageTagsList excludedPackageTags);
void removeUser(int userHandle);
void startWatchingActive(in int[] ops, IAppOpsActiveCallback callback);

View File

@@ -169,7 +169,7 @@ public class SystemConfig {
// 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 ArraySet<String> mAllowIgnoreLocationSettings = new ArraySet<>();
final ArrayMap<String, ArraySet<String>> mAllowIgnoreLocationSettings = new ArrayMap<>();
// These are the action strings of broadcasts which are whitelisted to
// be delivered anonymously even to apps which target O+.
@@ -313,7 +313,7 @@ public class SystemConfig {
return mAllowUnthrottledLocation;
}
public ArraySet<String> getAllowIgnoreLocationSettings() {
public ArrayMap<String, ArraySet<String>> getAllowIgnoreLocationSettings() {
return mAllowIgnoreLocationSettings;
}
@@ -867,11 +867,25 @@ public class SystemConfig {
case "allow-ignore-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 {
mAllowIgnoreLocationSettings.add(pkgname);
ArraySet<String> tags = mAllowIgnoreLocationSettings.get(pkgname);
if (tags == null || !tags.isEmpty()) {
if (tags == null) {
tags = new ArraySet<>(1);
mAllowIgnoreLocationSettings.put(pkgname, tags);
}
if (!"*".equals(attributionTag)) {
if ("null".equals(attributionTag)) {
attributionTag = null;
}
tags.add(attributionTag);
}
}
}
} else {
logNotAllowedInPartition(name, permFile, parser);

View File

@@ -0,0 +1,109 @@
/*
* 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 android.os;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
import android.util.ArraySet;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Arrays;
@Presubmit
@RunWith(AndroidJUnit4.class)
public class PackageTagsListTest {
@Test
public void testPackageTagsList() {
PackageTagsList.Builder builder = new PackageTagsList.Builder()
.add("package1", "attr1")
.add("package1", "attr2")
.add("package2");
PackageTagsList list = builder.build();
assertTrue(list.contains(builder.build()));
assertTrue(list.contains("package1", "attr1"));
assertTrue(list.contains("package1", "attr2"));
assertTrue(list.contains("package2", "attr1"));
assertTrue(list.contains("package2", "attr2"));
assertTrue(list.contains("package2", "attr3"));
assertTrue(list.containsAll("package2"));
assertTrue(list.includes("package1"));
assertTrue(list.includes("package2"));
assertFalse(list.contains("package1", "attr3"));
assertFalse(list.containsAll("package1"));
assertFalse(list.includes("package3"));
PackageTagsList bigList = builder.add("package3").build();
assertTrue(bigList.contains(builder.build()));
assertTrue(bigList.contains(list));
assertFalse(list.contains(bigList));
}
@Test
public void testPackageTagsList_BuildFromMap() {
ArrayMap<String, ArraySet<String>> map = new ArrayMap<>();
map.put("package1", new ArraySet<>(Arrays.asList("attr1", "attr2")));
map.put("package2", new ArraySet<>());
PackageTagsList.Builder builder = new PackageTagsList.Builder().add(map);
PackageTagsList list = builder.build();
assertTrue(list.contains(builder.build()));
assertTrue(list.contains("package1", "attr1"));
assertTrue(list.contains("package1", "attr2"));
assertTrue(list.contains("package2", "attr1"));
assertTrue(list.contains("package2", "attr2"));
assertTrue(list.contains("package2", "attr3"));
assertTrue(list.containsAll("package2"));
assertTrue(list.includes("package1"));
assertTrue(list.includes("package2"));
assertFalse(list.contains("package1", "attr3"));
assertFalse(list.containsAll("package1"));
assertFalse(list.includes("package3"));
map.put("package3", new ArraySet<>());
PackageTagsList bigList = builder.add(map).build();
assertTrue(bigList.contains(builder.build()));
assertTrue(bigList.contains(list));
assertFalse(list.contains(bigList));
}
@Test
public void testWriteToParcel() {
PackageTagsList list = new PackageTagsList.Builder()
.add("package1", "attr1")
.add("package1", "attr2")
.add("package2")
.build();
Parcel parcel = Parcel.obtain();
list.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
PackageTagsList newList = PackageTagsList.CREATOR.createFromParcel(parcel);
parcel.recycle();
assertEquals(list, newList);
}
}

View File

@@ -98,6 +98,7 @@
</xs:complexType>
<xs:complexType name="allow-ignore-location-settings">
<xs:attribute name="package" type="xs:string"/>
<xs:attribute name="attributionTag" type="xs:string"/>
</xs:complexType>
<xs:complexType name="allow-implicit-broadcast">
<xs:attribute name="action" type="xs:string"/>

View File

@@ -11,7 +11,9 @@ package com.android.xml.permission.configfile {
public class AllowIgnoreLocationSettings {
ctor public AllowIgnoreLocationSettings();
method public String getAttributionTag();
method public String get_package();
method public void setAttributionTag(String);
method public void set_package(String);
}

View File

@@ -41,6 +41,7 @@ import android.location.provider.IProviderRequestListener;
import android.location.provider.ProviderProperties;
import android.os.Bundle;
import android.os.ICancellationSignal;
import android.os.PackageTagsList;
/**
* System private API for talking with the location service.
@@ -133,5 +134,5 @@ interface ILocationManager
// used by gts tests to verify whitelists
String[] getBackgroundThrottlingWhitelist();
String[] getIgnoreSettingsWhitelist();
PackageTagsList getIgnoreSettingsAllowlist();
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2021 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 android.location;
import android.annotation.SystemApi;
import android.annotation.TestApi;
/**
* DeviceConfig keys within the location namespace.
*
* @hide
*/
@SystemApi
@TestApi
public final class LocationDeviceConfig {
/**
* 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.
*
* <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>
* <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>
* </ul>
*/
public static final String IGNORE_SETTINGS_ALLOWLIST = "ignore_settings_allowlist";
private LocationDeviceConfig() {}
}

View File

@@ -58,6 +58,7 @@ import android.os.HandlerExecutor;
import android.os.ICancellationSignal;
import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.PackageTagsList;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -447,12 +448,23 @@ public class LocationManager {
}
/**
* @deprecated Do not use.
* @hide
*/
@Deprecated
@TestApi
public @NonNull String[] getIgnoreSettingsWhitelist() {
return new String[0];
}
/**
* For testing purposes only.
* @hide
*/
@TestApi
public @NonNull String[] getIgnoreSettingsWhitelist() {
public @NonNull PackageTagsList getIgnoreSettingsAllowlist() {
try {
return mService.getIgnoreSettingsWhitelist();
return mService.getIgnoreSettingsAllowlist();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}

View File

@@ -896,9 +896,6 @@ class SettingsProtoDumpUtil {
dumpSetting(s, p,
Settings.Global.GNSS_HAL_LOCATION_REQUEST_DURATION_MILLIS,
GlobalSettingsProto.Location.GNSS_HAL_LOCATION_REQUEST_DURATION_MILLIS);
dumpSetting(s, p,
Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST,
GlobalSettingsProto.Location.IGNORE_SETTINGS_PACKAGE_WHITELIST);
p.end(locationToken);
final long lpmToken = p.start(GlobalSettingsProto.LOW_POWER_MODE);

View File

@@ -321,7 +321,6 @@ public class SettingsBackupTest {
Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST,
Settings.Global.LOCATION_ENABLE_STATIONARY_THROTTLE,
Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST,
Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED,
Settings.Global.LOCK_SOUND,
Settings.Global.LOOPER_STATS,

View File

@@ -116,6 +116,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.PackageTagsList;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteCallbackList;
@@ -132,6 +133,7 @@ import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.IndentingPrintWriter;
import android.util.KeyValueListParser;
import android.util.LongSparseArray;
import android.util.Pair;
@@ -6194,17 +6196,19 @@ public class AppOpsService extends IAppOpsService.Stub {
final int excludedPackageCount = restrictionState.perUserExcludedPackageTags != null
? restrictionState.perUserExcludedPackageTags.size() : 0;
if (excludedPackageCount > 0 && dumpOp < 0) {
IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
ipw.increaseIndent();
boolean printedPackagesHeader = false;
for (int j = 0; j < excludedPackageCount; j++) {
int userId = restrictionState.perUserExcludedPackageTags.keyAt(j);
Map<String, String[]> packageNames =
PackageTagsList packageNames =
restrictionState.perUserExcludedPackageTags.valueAt(j);
if (packageNames == null) {
continue;
}
boolean hasPackage;
if (dumpPackage != null) {
hasPackage = packageNames.containsKey(dumpPackage);
hasPackage = packageNames.includes(dumpPackage);
} else {
hasPackage = true;
}
@@ -6212,32 +6216,29 @@ public class AppOpsService extends IAppOpsService.Stub {
continue;
}
if (!printedTokenHeader) {
pw.println(" User restrictions for token " + token + ":");
ipw.println("User restrictions for token " + token + ":");
printedTokenHeader = true;
}
ipw.increaseIndent();
if (!printedPackagesHeader) {
pw.println(" Excluded packages:");
ipw.println("Excluded packages:");
printedPackagesHeader = true;
}
pw.print(" ");
pw.print("user: ");
pw.print(userId);
pw.println(" packages: ");
for (Map.Entry<String, String[]> entry : packageNames.entrySet()) {
if (entry.getValue() == null) {
continue;
}
pw.print(" ");
pw.print(entry.getKey());
pw.print(": ");
if (entry.getValue().length == 0) {
pw.print("*");
} else {
pw.print(Arrays.toString(entry.getValue()));
}
pw.println();
}
ipw.increaseIndent();
ipw.print("user: ");
ipw.print(userId);
ipw.println(" packages: ");
ipw.increaseIndent();
packageNames.dump(ipw);
ipw.decreaseIndent();
ipw.decreaseIndent();
ipw.decreaseIndent();
}
ipw.decreaseIndent();
}
}
}
@@ -6270,7 +6271,7 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle,
Map<String, String[]> excludedPackageTags) {
PackageTagsList excludedPackageTags) {
if (Binder.getCallingPid() != Process.myPid()) {
mContext.enforcePermission(Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS,
Binder.getCallingPid(), Binder.getCallingUid(), null);
@@ -6290,7 +6291,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token,
int userHandle, Map<String, String[]> excludedPackageTags) {
int userHandle, PackageTagsList excludedPackageTags) {
synchronized (AppOpsService.this) {
ClientRestrictionState restrictionState = mOpUserRestrictions.get(token);
@@ -6835,7 +6836,7 @@ public class AppOpsService extends IAppOpsService.Stub {
private final class ClientRestrictionState implements DeathRecipient {
private final IBinder token;
SparseArray<boolean[]> perUserRestrictions;
SparseArray<Map<String, String[]>> perUserExcludedPackageTags;
SparseArray<PackageTagsList> perUserExcludedPackageTags;
public ClientRestrictionState(IBinder token)
throws RemoteException {
@@ -6844,7 +6845,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
public boolean setRestriction(int code, boolean restricted,
Map<String, String[]> excludedPackageTags, int userId) {
PackageTagsList excludedPackageTags, int userId) {
boolean changed = false;
if (perUserRestrictions == null && restricted) {
@@ -6886,7 +6887,8 @@ public class AppOpsService extends IAppOpsService.Stub {
}
if (userRestrictions != null) {
final boolean noExcludedPackages = ArrayUtils.isEmpty(excludedPackageTags);
final boolean noExcludedPackages =
excludedPackageTags == null || excludedPackageTags.isEmpty();
if (perUserExcludedPackageTags == null && !noExcludedPackages) {
perUserExcludedPackageTags = new SparseArray<>();
}
@@ -6897,16 +6899,7 @@ public class AppOpsService extends IAppOpsService.Stub {
perUserExcludedPackageTags = null;
}
} else {
Map<String, String[]> userExcludedPackageTags =
perUserExcludedPackageTags.get(thisUserId);
if (userExcludedPackageTags == null) {
userExcludedPackageTags = new ArrayMap<>(
excludedPackageTags.size());
perUserExcludedPackageTags.put(thisUserId,
userExcludedPackageTags);
}
userExcludedPackageTags.clear();
userExcludedPackageTags.putAll(excludedPackageTags);
perUserExcludedPackageTags.put(thisUserId, excludedPackageTags);
}
changed = true;
}
@@ -6932,19 +6925,11 @@ public class AppOpsService extends IAppOpsService.Stub {
if (perUserExcludedPackageTags == null) {
return true;
}
Map<String, String[]> perUserExclusions = perUserExcludedPackageTags.get(userId);
PackageTagsList perUserExclusions = perUserExcludedPackageTags.get(userId);
if (perUserExclusions == null) {
return true;
}
String[] excludedTags = perUserExclusions.get(packageName);
if (excludedTags == null) {
return true;
}
if (excludedTags.length == 0) {
// all attribution tags within the package are excluded
return false;
}
return !ArrayUtils.contains(excludedTags, attributionTag);
return !perUserExclusions.contains(packageName, attributionTag);
}
public void removeUser(int userId) {

View File

@@ -76,6 +76,7 @@ import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.ICancellationSignal;
import android.os.PackageTagsList;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
@@ -139,7 +140,6 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -271,7 +271,7 @@ public class LocationManagerService extends ILocationManager.Stub implements
mInjector.getSettingsHelper().addOnLocationEnabledChangedListener(
this::onLocationModeChanged);
mInjector.getSettingsHelper().addOnIgnoreSettingsPackageWhitelistChangedListener(
mInjector.getSettingsHelper().addIgnoreSettingsAllowlistChangedListener(
() -> refreshAppOpsRestrictions(UserHandle.USER_ALL));
mInjector.getUserInfoHelper().addListener((userId, change) -> {
if (change == UserInfoHelper.UserListener.USER_STARTED) {
@@ -641,9 +641,8 @@ public class LocationManagerService extends ILocationManager.Stub implements
}
@Override
public String[] getIgnoreSettingsWhitelist() {
return mInjector.getSettingsHelper().getIgnoreSettingsPackageWhitelist().toArray(
new String[0]);
public PackageTagsList getIgnoreSettingsAllowlist() {
return mInjector.getSettingsHelper().getIgnoreSettingsAllowlist();
}
@Nullable
@@ -1408,26 +1407,17 @@ public class LocationManagerService extends ILocationManager.Stub implements
boolean enabled = mInjector.getSettingsHelper().isLocationEnabled(userId);
ArrayMap<String, String[]> allowedPackages = null;
PackageTagsList allowedPackages = null;
if (!enabled) {
ArrayMap<String, ArraySet<String>> packages = new ArrayMap<>();
PackageTagsList.Builder builder = new PackageTagsList.Builder();
for (LocationProviderManager manager : mProviderManagers) {
CallerIdentity identity = manager.getIdentity();
if (identity != null) {
packages.computeIfAbsent(identity.getPackageName(), k -> new ArraySet<>()).add(
identity.getAttributionTag());
builder.add(identity.getPackageName(), identity.getAttributionTag());
}
}
for (String packageName :
mInjector.getSettingsHelper().getIgnoreSettingsPackageWhitelist()) {
packages.computeIfAbsent(packageName, k -> new ArraySet<>()).clear();
}
packages.computeIfAbsent(mContext.getPackageName(), k -> new ArraySet<>()).clear();
allowedPackages = new ArrayMap<>();
for (Map.Entry<String, ArraySet<String>> entry : packages.entrySet()) {
allowedPackages.put(entry.getKey(), entry.getValue().toArray(new String[0]));
}
builder.add(mInjector.getSettingsHelper().getIgnoreSettingsAllowlist());
allowedPackages = builder.build();
}
AppOpsManager appOpsManager = Objects.requireNonNull(

View File

@@ -16,6 +16,7 @@
package com.android.server.location.injector;
import android.os.PackageTagsList;
import android.util.IndentingPrintWriter;
import java.io.FileDescriptor;
@@ -146,21 +147,21 @@ public abstract class SettingsHelper {
GlobalSettingChangedListener listener);
/**
* Retrieve the ignore settings package whitelist.
* Retrieve the ignore location settings package+tags allowlist setting.
*/
public abstract Set<String> getIgnoreSettingsPackageWhitelist();
public abstract PackageTagsList getIgnoreSettingsAllowlist();
/**
* Add a listener for changes to the ignore settings package whitelist. Callbacks occur on an
* unspecified thread.
*/
public abstract void addOnIgnoreSettingsPackageWhitelistChangedListener(
public abstract void addIgnoreSettingsAllowlistChangedListener(
GlobalSettingChangedListener listener);
/**
* Remove a listener for changes to the ignore settings package whitelist.
*/
public abstract void removeOnIgnoreSettingsPackageWhitelistChangedListener(
public abstract void removeIgnoreSettingsAllowlistChangedListener(
GlobalSettingChangedListener listener);
/**

View File

@@ -16,11 +16,11 @@
package com.android.server.location.injector;
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;
import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST;
import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS;
import static android.provider.Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST;
import static android.provider.Settings.Secure.LOCATION_COARSE_ACCURACY_M;
import static android.provider.Settings.Secure.LOCATION_MODE;
import static android.provider.Settings.Secure.LOCATION_MODE_OFF;
@@ -35,10 +35,13 @@ import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
import android.os.PackageTagsList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import android.util.Log;
@@ -77,7 +80,7 @@ public class SystemSettingsHelper extends SettingsHelper {
private final StringListCachedSecureSetting mLocationPackageBlacklist;
private final StringListCachedSecureSetting mLocationPackageWhitelist;
private final StringSetCachedGlobalSetting mBackgroundThrottlePackageWhitelist;
private final StringSetCachedGlobalSetting mIgnoreSettingsPackageWhitelist;
private final PackageTagsListSetting mIgnoreSettingsPackageAllowlist;
public SystemSettingsHelper(Context context) {
mContext = context;
@@ -95,10 +98,9 @@ public class SystemSettingsHelper extends SettingsHelper {
LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST,
() -> SystemConfig.getInstance().getAllowUnthrottledLocation(),
FgThread.getHandler());
mIgnoreSettingsPackageWhitelist = new StringSetCachedGlobalSetting(context,
LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST,
() -> SystemConfig.getInstance().getAllowIgnoreLocationSettings(),
FgThread.getHandler());
mIgnoreSettingsPackageAllowlist = new PackageTagsListSetting(
IGNORE_SETTINGS_ALLOWLIST,
() -> SystemConfig.getInstance().getAllowIgnoreLocationSettings());
}
/** Called when system is ready. */
@@ -108,20 +110,14 @@ public class SystemSettingsHelper extends SettingsHelper {
mLocationPackageBlacklist.register();
mLocationPackageWhitelist.register();
mBackgroundThrottlePackageWhitelist.register();
mIgnoreSettingsPackageWhitelist.register();
mIgnoreSettingsPackageAllowlist.register();
}
/**
* Retrieve if location is enabled or not.
*/
@Override
public boolean isLocationEnabled(int userId) {
return mLocationMode.getValueForUser(LOCATION_MODE_OFF, userId) != LOCATION_MODE_OFF;
}
/**
* Set location enabled for a user.
*/
@Override
public void setLocationEnabled(boolean enabled, int userId) {
final long identity = Binder.clearCallingIdentity();
@@ -138,53 +134,33 @@ public class SystemSettingsHelper extends SettingsHelper {
}
}
/**
* Add a listener for changes to the location enabled setting. Callbacks occur on an unspecified
* thread.
*/
@Override
public void addOnLocationEnabledChangedListener(UserSettingChangedListener listener) {
mLocationMode.addListener(listener);
}
/**
* Remove a listener for changes to the location enabled setting.
*/
@Override
public void removeOnLocationEnabledChangedListener(UserSettingChangedListener listener) {
mLocationMode.removeListener(listener);
}
/**
* Retrieve the background throttle interval.
*/
@Override
public long getBackgroundThrottleIntervalMs() {
return mBackgroundThrottleIntervalMs.getValue(DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
}
/**
* Add a listener for changes to the background throttle interval. Callbacks occur on an
* unspecified thread.
*/
@Override
public void addOnBackgroundThrottleIntervalChangedListener(
GlobalSettingChangedListener listener) {
mBackgroundThrottleIntervalMs.addListener(listener);
}
/**
* Remove a listener for changes to the background throttle interval.
*/
@Override
public void removeOnBackgroundThrottleIntervalChangedListener(
GlobalSettingChangedListener listener) {
mBackgroundThrottleIntervalMs.removeListener(listener);
}
/**
* Check if the given package is blacklisted for location access.
*/
@Override
public boolean isLocationPackageBlacklisted(int userId, String packageName) {
List<String> locationPackageBlacklist = mLocationPackageBlacklist.getValueForUser(userId);
@@ -208,10 +184,6 @@ public class SystemSettingsHelper extends SettingsHelper {
return false;
}
/**
* Add a listener for changes to the location package blacklist. Callbacks occur on an
* unspecified thread.
*/
@Override
public void addOnLocationPackageBlacklistChangedListener(
UserSettingChangedListener listener) {
@@ -219,9 +191,6 @@ public class SystemSettingsHelper extends SettingsHelper {
mLocationPackageWhitelist.addListener(listener);
}
/**
* Remove a listener for changes to the location package blacklist.
*/
@Override
public void removeOnLocationPackageBlacklistChangedListener(
UserSettingChangedListener listener) {
@@ -229,90 +198,57 @@ public class SystemSettingsHelper extends SettingsHelper {
mLocationPackageWhitelist.removeListener(listener);
}
/**
* Retrieve the background throttle package whitelist.
*/
@Override
public Set<String> getBackgroundThrottlePackageWhitelist() {
return mBackgroundThrottlePackageWhitelist.getValue();
}
/**
* Add a listener for changes to the background throttle package whitelist. Callbacks occur on
* an unspecified thread.
*/
@Override
public void addOnBackgroundThrottlePackageWhitelistChangedListener(
GlobalSettingChangedListener listener) {
mBackgroundThrottlePackageWhitelist.addListener(listener);
}
/**
* Remove a listener for changes to the background throttle package whitelist.
*/
@Override
public void removeOnBackgroundThrottlePackageWhitelistChangedListener(
GlobalSettingChangedListener listener) {
mBackgroundThrottlePackageWhitelist.removeListener(listener);
}
/**
* Retrieve the gnss measurements full tracking enabled setting.
*/
@Override
public boolean isGnssMeasurementsFullTrackingEnabled() {
return mGnssMeasurementFullTracking.getValue(false);
}
/**
* Add a listener for changes to the background throttle package whitelist. Callbacks occur on
* an unspecified thread.
*/
@Override
public void addOnGnssMeasurementsFullTrackingEnabledChangedListener(
GlobalSettingChangedListener listener) {
mGnssMeasurementFullTracking.addListener(listener);
}
/**
* Remove a listener for changes to the background throttle package whitelist.
*/
@Override
public void removeOnGnssMeasurementsFullTrackingEnabledChangedListener(
GlobalSettingChangedListener listener) {
mGnssMeasurementFullTracking.removeListener(listener);
}
/**
* Retrieve the ignore settings package whitelist.
*/
@Override
public Set<String> getIgnoreSettingsPackageWhitelist() {
return mIgnoreSettingsPackageWhitelist.getValue();
public PackageTagsList getIgnoreSettingsAllowlist() {
return mIgnoreSettingsPackageAllowlist.getValue();
}
/**
* Add a listener for changes to the ignore settings package whitelist. Callbacks occur on an
* unspecified thread.
*/
@Override
public void addOnIgnoreSettingsPackageWhitelistChangedListener(
public void addIgnoreSettingsAllowlistChangedListener(
GlobalSettingChangedListener listener) {
mIgnoreSettingsPackageWhitelist.addListener(listener);
mIgnoreSettingsPackageAllowlist.addListener(listener);
}
/**
* Remove a listener for changes to the ignore settings package whitelist.
*/
@Override
public void removeOnIgnoreSettingsPackageWhitelistChangedListener(
public void removeIgnoreSettingsAllowlistChangedListener(
GlobalSettingChangedListener listener) {
mIgnoreSettingsPackageWhitelist.removeListener(listener);
mIgnoreSettingsPackageAllowlist.removeListener(listener);
}
/**
* Retrieve the background throttling proximity alert interval.
*/
@Override
public long getBackgroundThrottleProximityAlertIntervalMs() {
final long identity = Binder.clearCallingIdentity();
@@ -325,10 +261,6 @@ public class SystemSettingsHelper extends SettingsHelper {
}
}
/**
* Retrieve the accuracy for coarsening location, ie, the grid size used for snap-to-grid
* coarsening.
*/
@Override
public float getCoarseLocationAccuracyM() {
final long identity = Binder.clearCallingIdentity();
@@ -344,9 +276,6 @@ public class SystemSettingsHelper extends SettingsHelper {
}
}
/**
* Dump info for debugging.
*/
@Override
public void dump(FileDescriptor fd, IndentingPrintWriter ipw, String[] args) {
int[] userIds;
@@ -428,13 +357,11 @@ public class SystemSettingsHelper extends SettingsHelper {
ipw.decreaseIndent();
}
Set<String> ignoreSettingsPackageWhitelist = mIgnoreSettingsPackageWhitelist.getValue();
if (!ignoreSettingsPackageWhitelist.isEmpty()) {
PackageTagsList ignoreSettingsAllowlist = mIgnoreSettingsPackageAllowlist.getValue();
if (!ignoreSettingsAllowlist.isEmpty()) {
ipw.println("Bypass Allow Packages:");
ipw.increaseIndent();
for (String packageName : ignoreSettingsPackageWhitelist) {
ipw.println(packageName);
}
ignoreSettingsAllowlist.dump(ipw);
ipw.decreaseIndent();
}
}
@@ -687,4 +614,139 @@ public class SystemSettingsHelper extends SettingsHelper {
super.onChange(selfChange, uri, userId);
}
}
private static class DeviceConfigSetting implements DeviceConfig.OnPropertiesChangedListener {
protected final String mName;
private final CopyOnWriteArrayList<GlobalSettingChangedListener> mListeners;
@GuardedBy("this")
private boolean mRegistered;
DeviceConfigSetting(String name) {
mName = name;
mListeners = new CopyOnWriteArrayList<>();
}
protected synchronized boolean isRegistered() {
return mRegistered;
}
protected synchronized void register() {
if (mRegistered) {
return;
}
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_LOCATION,
FgThread.getExecutor(), this);
mRegistered = true;
}
public void addListener(GlobalSettingChangedListener listener) {
mListeners.add(listener);
}
public void removeListener(GlobalSettingChangedListener listener) {
mListeners.remove(listener);
}
@Override
public final void onPropertiesChanged(DeviceConfig.Properties properties) {
if (!properties.getKeyset().contains(mName)) {
return;
}
onPropertiesChanged();
}
public void onPropertiesChanged() {
if (D) {
Log.d(TAG, "location device config setting changed: " + mName);
}
for (UserSettingChangedListener listener : mListeners) {
listener.onSettingChanged(UserHandle.USER_ALL);
}
}
}
private static class PackageTagsListSetting extends DeviceConfigSetting {
private final Supplier<ArrayMap<String, ArraySet<String>>> mBaseValuesSupplier;
@GuardedBy("this")
private boolean mValid;
@GuardedBy("this")
private PackageTagsList mCachedValue;
PackageTagsListSetting(String name,
Supplier<ArrayMap<String, ArraySet<String>>> baseValuesSupplier) {
super(name);
mBaseValuesSupplier = baseValuesSupplier;
}
public synchronized PackageTagsList getValue() {
PackageTagsList value = mCachedValue;
if (!mValid) {
final long identity = Binder.clearCallingIdentity();
try {
PackageTagsList.Builder builder = new PackageTagsList.Builder().add(
mBaseValuesSupplier.get());
String setting = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_LOCATION,
mName);
if (!TextUtils.isEmpty(setting)) {
for (String packageAndTags : setting.split(",")) {
if (TextUtils.isEmpty(packageAndTags)) {
continue;
}
String[] packageThenTags = packageAndTags.split(";");
String packageName = packageThenTags[0];
if (packageThenTags.length == 1) {
builder.add(packageName);
} else {
for (int i = 1; i < packageThenTags.length; i++) {
String attributionTag = packageThenTags[i];
if ("null".equals(attributionTag)) {
attributionTag = null;
}
if ("*".equals(attributionTag)) {
builder.add(packageName);
} else {
builder.add(packageName, attributionTag);
}
}
}
}
}
value = builder.build();
} finally {
Binder.restoreCallingIdentity(identity);
}
if (isRegistered()) {
mValid = true;
mCachedValue = value;
}
}
return value;
}
public synchronized void invalidate() {
mValid = false;
mCachedValue = null;
}
@Override
public void onPropertiesChanged() {
invalidate();
super.onPropertiesChanged();
}
}
}

View File

@@ -613,9 +613,9 @@ public class LocationProviderManager extends
boolean locationSettingsIgnored = baseRequest.isLocationSettingsIgnored();
if (locationSettingsIgnored) {
// if we are not currently allowed use location settings ignored, disable it
if (!mSettingsHelper.getIgnoreSettingsPackageWhitelist().contains(
getIdentity().getPackageName()) && !mLocationManagerInternal.isProvider(
null, getIdentity())) {
if (!mSettingsHelper.getIgnoreSettingsAllowlist().contains(
getIdentity().getPackageName(), getIdentity().getAttributionTag())
&& !mLocationManagerInternal.isProvider(null, getIdentity())) {
builder.setLocationSettingsIgnored(false);
locationSettingsIgnored = false;
}
@@ -1820,7 +1820,7 @@ public class LocationProviderManager extends
mBackgroundThrottlePackageWhitelistChangedListener);
mSettingsHelper.addOnLocationPackageBlacklistChangedListener(
mLocationPackageBlacklistChangedListener);
mSettingsHelper.addOnIgnoreSettingsPackageWhitelistChangedListener(
mSettingsHelper.addIgnoreSettingsAllowlistChangedListener(
mIgnoreSettingsPackageWhitelistChangedListener);
mLocationPermissionsHelper.addListener(mLocationPermissionsListener);
mAppForegroundHelper.addListener(mAppForegroundChangedListener);
@@ -1841,7 +1841,7 @@ public class LocationProviderManager extends
mBackgroundThrottlePackageWhitelistChangedListener);
mSettingsHelper.removeOnLocationPackageBlacklistChangedListener(
mLocationPackageBlacklistChangedListener);
mSettingsHelper.removeOnIgnoreSettingsPackageWhitelistChangedListener(
mSettingsHelper.removeIgnoreSettingsAllowlistChangedListener(
mIgnoreSettingsPackageWhitelistChangedListener);
mLocationPermissionsHelper.removeListener(mLocationPermissionsListener);
mAppForegroundHelper.removeListener(mAppForegroundChangedListener);

View File

@@ -42,6 +42,7 @@ import android.os.IBinder;
import android.os.IInterface;
import android.os.Looper;
import android.os.Message;
import android.os.PackageTagsList;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -85,7 +86,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
@@ -856,14 +856,13 @@ public class VrManagerService extends SystemService
// If user changed drop restrictions for the old user.
if (oldUserId != newUserId) {
appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
false, mOverlayToken, (Map<String, String[]>) null, oldUserId);
false, mOverlayToken, null, oldUserId);
}
// Apply the restrictions for the current user based on vr state
ArrayMap<String, String[]> exemptions = null;
PackageTagsList exemptions = null;
if (exemptedPackage != null) {
exemptions = new ArrayMap<>(1);
exemptions.put(exemptedPackage, new String[0]);
exemptions = new PackageTagsList.Builder(1).add(exemptedPackage).build();
}
appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,

View File

@@ -16,6 +16,7 @@
package com.android.server.location.injector;
import android.os.PackageTagsList;
import android.os.UserHandle;
import android.util.IndentingPrintWriter;
import android.util.SparseArray;
@@ -40,7 +41,7 @@ public class FakeSettingsHelper extends SettingsHelper {
private final CopyOnWriteArrayList<UserSettingChangedListener> mListeners;
private Setting(Object defaultValue) {
Setting(Object defaultValue) {
mValues = new SparseArray<>();
mDefaultValue = defaultValue;
mListeners = new CopyOnWriteArrayList<>();
@@ -83,7 +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 mIgnoreSettingsPackageWhitelist = new Setting(Collections.emptySet());
private final Setting mIgnoreSettingsAllowlist = new Setting(
new PackageTagsList.Builder().build());
private final Setting mBackgroundThrottleProximityAlertIntervalSetting = new Setting(
30 * 60 * 1000L);
private final Setting mCoarseLocationAccuracySetting = new Setting(2000.0f);
@@ -192,24 +194,24 @@ public class FakeSettingsHelper extends SettingsHelper {
}
@Override
public Set<String> getIgnoreSettingsPackageWhitelist() {
return mIgnoreSettingsPackageWhitelist.getValue(Set.class);
public PackageTagsList getIgnoreSettingsAllowlist() {
return mIgnoreSettingsAllowlist.getValue(PackageTagsList.class);
}
public void setIgnoreSettingsPackageWhitelist(Set<String> newValue) {
mIgnoreSettingsPackageWhitelist.setValue(newValue);
public void setIgnoreSettingsAllowlist(PackageTagsList newValue) {
mIgnoreSettingsAllowlist.setValue(newValue);
}
@Override
public void addOnIgnoreSettingsPackageWhitelistChangedListener(
public void addIgnoreSettingsAllowlistChangedListener(
GlobalSettingChangedListener listener) {
mIgnoreSettingsPackageWhitelist.addListener(listener);
mIgnoreSettingsAllowlist.addListener(listener);
}
@Override
public void removeOnIgnoreSettingsPackageWhitelistChangedListener(
public void removeIgnoreSettingsAllowlistChangedListener(
GlobalSettingChangedListener listener) {
mIgnoreSettingsPackageWhitelist.removeListener(listener);
mIgnoreSettingsAllowlist.removeListener(listener);
}
@Override

View File

@@ -71,6 +71,7 @@ import android.location.util.identity.CallerIdentity;
import android.os.Bundle;
import android.os.ICancellationSignal;
import android.os.IRemoteCallback;
import android.os.PackageTagsList;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
@@ -923,8 +924,9 @@ public class LocationProviderManagerTest {
@Test
public void testProviderRequest_IgnoreLocationSettings() {
mInjector.getSettingsHelper().setIgnoreSettingsPackageWhitelist(
Collections.singleton(IDENTITY.getPackageName()));
mInjector.getSettingsHelper().setIgnoreSettingsAllowlist(
new PackageTagsList.Builder().add(
IDENTITY.getPackageName()).build());
ILocationListener listener1 = createMockLocationListener();
LocationRequest request1 = new LocationRequest.Builder(5)
@@ -950,8 +952,9 @@ public class LocationProviderManagerTest {
@Test
public void testProviderRequest_IgnoreLocationSettings_ProviderDisabled() {
mInjector.getSettingsHelper().setIgnoreSettingsPackageWhitelist(
Collections.singleton(IDENTITY.getPackageName()));
mInjector.getSettingsHelper().setIgnoreSettingsAllowlist(
new PackageTagsList.Builder().add(
IDENTITY.getPackageName()).build());
ILocationListener listener1 = createMockLocationListener();
LocationRequest request1 = new LocationRequest.Builder(1)
@@ -975,8 +978,9 @@ public class LocationProviderManagerTest {
@Test
public void testProviderRequest_IgnoreLocationSettings_NoAllowlist() {
mInjector.getSettingsHelper().setIgnoreSettingsPackageWhitelist(
Collections.singleton(IDENTITY.getPackageName()));
mInjector.getSettingsHelper().setIgnoreSettingsAllowlist(
new PackageTagsList.Builder().add(
IDENTITY.getPackageName()).build());
ILocationListener listener = createMockLocationListener();
LocationRequest request = new LocationRequest.Builder(1)
@@ -985,7 +989,8 @@ public class LocationProviderManagerTest {
.build();
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
mInjector.getSettingsHelper().setIgnoreSettingsPackageWhitelist(Collections.emptySet());
mInjector.getSettingsHelper().setIgnoreSettingsAllowlist(
new PackageTagsList.Builder().build());
assertThat(mProvider.getRequest().isActive()).isTrue();
assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(1);
@@ -994,8 +999,9 @@ public class LocationProviderManagerTest {
@Test
public void testProviderRequest_BackgroundThrottle_IgnoreLocationSettings() {
mInjector.getSettingsHelper().setIgnoreSettingsPackageWhitelist(
Collections.singleton(IDENTITY.getPackageName()));
mInjector.getSettingsHelper().setIgnoreSettingsAllowlist(
new PackageTagsList.Builder().add(
IDENTITY.getPackageName()).build());
ILocationListener listener1 = createMockLocationListener();
LocationRequest request1 = new LocationRequest.Builder(5)