summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorNate Jiang <qiangjiang@google.com>2019-07-15 12:03:52 -0700
committerNate Jiang <qiangjiang@google.com>2019-07-25 17:21:17 +0000
commit985901cea5d3ce2a534ffd7fff485abb2411de61 (patch)
tree9a6dca9902d438209fd7ce85de602b6bc26d70c7 /service
parentf272b21563525d7c21735df8202a6e90e43f5b77 (diff)
[WifiNetworkFactory] Trim user approval list per App
Add capacity limit of APs for each App, remove least recently used ones when capacity is exceeded. Bug: 137129535 Test: atest android.net.wifi Test: atest com.android.server.wifi Change-Id: I5c1b7fa9c6ccc35e63f96c49e645bdb4ee7a5b77
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/NetworkRequestStoreData.java4
-rw-r--r--service/java/com/android/server/wifi/WifiNetworkFactory.java53
2 files changed, 39 insertions, 18 deletions
diff --git a/service/java/com/android/server/wifi/NetworkRequestStoreData.java b/service/java/com/android/server/wifi/NetworkRequestStoreData.java
index b74e64423..8d1244f05 100644
--- a/service/java/com/android/server/wifi/NetworkRequestStoreData.java
+++ b/service/java/com/android/server/wifi/NetworkRequestStoreData.java
@@ -29,7 +29,7 @@ import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@@ -213,7 +213,7 @@ public class NetworkRequestStoreData implements WifiConfigStore.StoreData {
*/
private Set<AccessPoint> parseApprovedAccessPoints(XmlPullParser in, int outerTagDepth)
throws XmlPullParserException, IOException {
- Set<AccessPoint> approvedAccessPoints = new HashSet<>();
+ Set<AccessPoint> approvedAccessPoints = new LinkedHashSet<>();
while (XmlUtil.gotoNextSectionWithNameOrEnd(
in, XML_TAG_SECTION_HEADER_ACCESS_POINT, outerTagDepth)) {
// Try/catch only runtime exceptions (like illegal args), any XML/IO exceptions are
diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java
index ecc1a9f18..1f060cf73 100644
--- a/service/java/com/android/server/wifi/WifiNetworkFactory.java
+++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java
@@ -68,6 +68,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -97,6 +98,9 @@ public class WifiNetworkFactory extends NetworkFactory {
@VisibleForTesting
public static final String UI_START_INTENT_EXTRA_REQUEST_IS_FOR_SINGLE_NETWORK =
"com.android.settings.wifi.extra.REQUEST_IS_FOR_SINGLE_NETWORK";
+ // Capacity limit of approved Access Point per App
+ @VisibleForTesting
+ public static final int NUM_OF_ACCESS_POINT_LIMIT_PER_APP = 50;
private final Context mContext;
private final ActivityManager mActivityManager;
@@ -117,8 +121,8 @@ public class WifiNetworkFactory extends NetworkFactory {
private final ExternalCallbackTracker<INetworkRequestMatchCallback> mRegisteredCallbacks;
private final Messenger mSrcMessenger;
// Store all user approved access points for apps.
- // TODO(b/122658039): Persist this.
- private final Map<String, Set<AccessPoint>> mUserApprovedAccessPointMap = new HashMap<>();
+ @VisibleForTesting
+ public final Map<String, LinkedHashSet<AccessPoint>> mUserApprovedAccessPointMap;
private WifiScanner mWifiScanner;
private int mGenericConnectionReqCount = 0;
@@ -346,12 +350,13 @@ public class WifiNetworkFactory extends NetworkFactory {
public Map<String, Set<AccessPoint>> toSerialize() {
// Clear the flag after writing to disk.
mHasNewDataToSerialize = false;
- return mUserApprovedAccessPointMap;
+ return new HashMap<>(mUserApprovedAccessPointMap);
}
@Override
public void fromDeserialized(Map<String, Set<AccessPoint>> approvedAccessPointMap) {
- mUserApprovedAccessPointMap.putAll(approvedAccessPointMap);
+ approvedAccessPointMap.forEach((key, value) ->
+ mUserApprovedAccessPointMap.put(key, new LinkedHashSet<>(value)));
}
@Override
@@ -397,6 +402,7 @@ public class WifiNetworkFactory extends NetworkFactory {
mConnectionTimeoutAlarmListener = new ConnectionTimeoutAlarmListener();
mRegisteredCallbacks = new ExternalCallbackTracker<INetworkRequestMatchCallback>(mHandler);
mSrcMessenger = new Messenger(new Handler(looper, mNetworkConnectionTriggerCallback));
+ mUserApprovedAccessPointMap = new HashMap<>();
// register the data store for serializing/deserializing data.
configStore.registerStoreData(
@@ -1235,6 +1241,9 @@ public class WifiNetworkFactory extends NetworkFactory {
new AccessPoint(scanResult.SSID,
MacAddress.fromString(scanResult.BSSID), fromScanResult.networkType);
if (approvedAccessPoints.contains(accessPoint)) {
+ // keep the most recently used AP in the end
+ approvedAccessPoints.remove(accessPoint);
+ approvedAccessPoints.add(accessPoint);
if (mVerboseLoggingEnabled) {
Log.v(TAG, "Found " + accessPoint
+ " in user approved access point for " + requestorPackageName);
@@ -1254,10 +1263,11 @@ public class WifiNetworkFactory extends NetworkFactory {
// object representing an entire network from UI, we need to ensure that all the visible
// BSSIDs matching the original request and the selected network are stored.
Set<AccessPoint> newUserApprovedAccessPoints = new HashSet<>();
+
+ ScanResultMatchInfo fromWifiConfiguration =
+ ScanResultMatchInfo.fromWifiConfiguration(network);
for (ScanResult scanResult : mActiveMatchedScanResults) {
ScanResultMatchInfo fromScanResult = ScanResultMatchInfo.fromScanResult(scanResult);
- ScanResultMatchInfo fromWifiConfiguration =
- ScanResultMatchInfo.fromWifiConfiguration(network);
if (fromScanResult.equals(fromWifiConfiguration)) {
AccessPoint approvedAccessPoint =
new AccessPoint(scanResult.SSID, MacAddress.fromString(scanResult.BSSID),
@@ -1268,10 +1278,10 @@ public class WifiNetworkFactory extends NetworkFactory {
if (newUserApprovedAccessPoints.isEmpty()) return;
String requestorPackageName = mActiveSpecificNetworkRequestSpecifier.requestorPackageName;
- Set<AccessPoint> approvedAccessPoints =
+ LinkedHashSet<AccessPoint> approvedAccessPoints =
mUserApprovedAccessPointMap.get(requestorPackageName);
if (approvedAccessPoints == null) {
- approvedAccessPoints = new HashSet<>();
+ approvedAccessPoints = new LinkedHashSet<>();
mUserApprovedAccessPointMap.put(requestorPackageName, approvedAccessPoints);
// Note the new app in metrics.
mWifiMetrics.incrementNetworkRequestApiNumApps();
@@ -1280,22 +1290,33 @@ public class WifiNetworkFactory extends NetworkFactory {
Log.v(TAG, "Adding " + newUserApprovedAccessPoints
+ " to user approved access point for " + requestorPackageName);
}
+ // keep the most recently added APs in the end
+ approvedAccessPoints.removeAll(newUserApprovedAccessPoints);
approvedAccessPoints.addAll(newUserApprovedAccessPoints);
+ cleanUpLRUAccessPoints(approvedAccessPoints);
saveToStore();
}
/**
+ * Clean up least recently used Access Points if specified app reach the limit.
+ */
+ private static void cleanUpLRUAccessPoints(Set<AccessPoint> approvedAccessPoints) {
+ if (approvedAccessPoints.size() <= NUM_OF_ACCESS_POINT_LIMIT_PER_APP) {
+ return;
+ }
+ Iterator iter = approvedAccessPoints.iterator();
+ while (iter.hasNext() && approvedAccessPoints.size() > NUM_OF_ACCESS_POINT_LIMIT_PER_APP) {
+ iter.next();
+ iter.remove();
+ }
+ }
+
+ /**
* Remove all user approved access points for the specified app.
*/
public void removeUserApprovedAccessPointsForApp(@NonNull String packageName) {
- Iterator<Map.Entry<String, Set<AccessPoint>>> iter =
- mUserApprovedAccessPointMap.entrySet().iterator();
- while (iter.hasNext()) {
- Map.Entry<String, Set<AccessPoint>> entry = iter.next();
- if (packageName.equals(entry.getKey())) {
- Log.i(TAG, "Removing all approved access points for " + packageName);
- iter.remove();
- }
+ if (mUserApprovedAccessPointMap.remove(packageName) != null) {
+ Log.i(TAG, "Removing all approved access points for " + packageName);
}
saveToStore();
}