wifi: Wi-Fi data usage per configuration (Wifi part) am: fa06a9c21d
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Wifi/+/1908675
Change-Id: I2856f193db3495a422b9bdc00305bf7ddb48a8cf
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index dda7481..1231f50 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -362,6 +362,7 @@
}
@Deprecated public class WifiConfiguration implements android.os.Parcelable {
+ method @Deprecated @NonNull public java.util.Set<java.lang.String> getAllPersistableNetworkKeys();
method @Deprecated public int getAuthType();
method @Deprecated public int getDeletionPriority();
method @Deprecated @NonNull public android.net.IpConfiguration getIpConfiguration();
@@ -494,6 +495,7 @@
}
public class WifiInfo implements android.os.Parcelable android.net.TransportInfo {
+ method @Nullable public String getCurrentNetworkKey();
method public double getLostTxPacketsPerSecond();
method @Nullable public String getRequestingPackageName();
method public double getRetriedTxPacketsPerSecond();
diff --git a/framework/java/android/net/wifi/WifiConfiguration.java b/framework/java/android/net/wifi/WifiConfiguration.java
index 924cd33..0859bd0 100644
--- a/framework/java/android/net/wifi/WifiConfiguration.java
+++ b/framework/java/android/net/wifi/WifiConfiguration.java
@@ -54,7 +54,9 @@
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -3939,4 +3941,55 @@
return SECURITY_TYPE_NAMES[securityType];
}
+ /**
+ * Returns the key for storing the data usage bucket.
+ *
+ * Note: DO NOT change this function. It is used to be a key to store Wi-Fi data usage data.
+ * Create a new function if we plan to change the key for Wi-Fi data usage and add the new key
+ * to {@link #getAllPersistableNetworkKeys()}.
+ *
+ * @param securityType the security type corresponding to the target network.
+ * @hide
+ */
+ public String getNetworkKeyFromSecurityType(@SecurityType int securityType) {
+ if (mPasspointUniqueId != null) {
+ // It might happen that there are two connections which use the same passpoint
+ // coniguration but different sim card (maybe same carriers?). Add subscriptionId to be
+ // the part of key to separate data in usage bucket.
+ // But now we only show one WifiConfiguration entry in Wifi picker for this case.
+ // It means that user only have a way to query usage with configuration on default SIM.
+ // (We always connect to network with default SIM). So returns the key with associated
+ // subscriptionId (the default one) first.
+ return subscriptionId + "-" + mPasspointUniqueId;
+ } else {
+ String key = SSID + getSecurityTypeName(securityType);
+ if (!shared) {
+ key += "-" + UserHandle.getUserHandleForUid(creatorUid).getIdentifier();
+ }
+ if (fromWifiNetworkSuggestion) {
+ key += "_" + creatorName + "-" + carrierId + "-" + subscriptionId;
+ }
+ return key;
+ }
+ }
+
+ /**
+ * Returns a list of all persistable network keys corresponding to this configuration.
+ * There may be multiple keys since they are security-type specific and a configuration may
+ * support multiple security types. The persistable key of a specific network connection may
+ * be obtained from {@link WifiInfo#getCurrentNetworkKey()}.
+ * An example of usage of such persistable network keys is to query the Wi-Fi data usage
+ * corresponding to this configuration. See {@code NetworkTemplate} to know the detail.
+ *
+ * @hide
+ */
+ @SystemApi
+ @NonNull
+ public Set<String> getAllPersistableNetworkKeys() {
+ Set<String> keys = new HashSet<>();
+ for (SecurityParams securityParam : mSecurityParamsList) {
+ keys.add(getNetworkKeyFromSecurityType(securityParam.getSecurityType()));
+ }
+ return keys;
+ }
}
diff --git a/framework/java/android/net/wifi/WifiInfo.java b/framework/java/android/net/wifi/WifiInfo.java
index ead4361..ed0288f 100644
--- a/framework/java/android/net/wifi/WifiInfo.java
+++ b/framework/java/android/net/wifi/WifiInfo.java
@@ -425,6 +425,11 @@
*/
private @IsPrimaryValues int mIsPrimary;
+ /**
+ * Key of the current network.
+ */
+ private String mCurrentNetworkKey;
+
/** @hide */
@UnsupportedAppUsage
public WifiInfo() {
@@ -438,6 +443,7 @@
mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
mSecurityType = -1;
mIsPrimary = IS_PRIMARY_FALSE;
+ mCurrentNetworkKey = null;
}
/** @hide */
@@ -477,6 +483,7 @@
mTxRetriedTxPacketsPerSecond = 0;
score = 0;
mSecurityType = -1;
+ mCurrentNetworkKey = null;
}
/**
@@ -544,6 +551,8 @@
mIsPrimary = shouldRedactNetworkSettingsFields(redactions)
? IS_PRIMARY_NO_PERMISSION : source.mIsPrimary;
mSecurityType = source.mSecurityType;
+ mCurrentNetworkKey = shouldRedactLocationSensitiveFields(redactions)
+ ? null : source.mCurrentNetworkKey;
}
}
@@ -1206,7 +1215,8 @@
.append(", score: ").append(Integer.toString(score))
.append(", CarrierMerged: ").append(mCarrierMerged)
.append(", SubscriptionId: ").append(mSubscriptionId)
- .append(", IsPrimary: ").append(mIsPrimary);
+ .append(", IsPrimary: ").append(mIsPrimary)
+ .append(mCurrentNetworkKey == null ? none : mCurrentNetworkKey);
return sb.toString();
}
@@ -1279,6 +1289,7 @@
dest.writeInt(mIsPrimary);
}
dest.writeInt(mSecurityType);
+ dest.writeString(mCurrentNetworkKey);
}
/** Implement the Parcelable interface {@hide} */
@@ -1334,6 +1345,7 @@
info.mIsPrimary = in.readInt();
}
info.mSecurityType = in.readInt();
+ info.mCurrentNetworkKey = in.readString();
return info;
}
@@ -1477,7 +1489,8 @@
&& Objects.equals(mPasspointUniqueId, thatWifiInfo.mPasspointUniqueId)
&& Objects.equals(mInformationElements, thatWifiInfo.mInformationElements)
&& Objects.equals(mIsPrimary, thatWifiInfo.mIsPrimary)
- && Objects.equals(mSecurityType, thatWifiInfo.mSecurityType);
+ && Objects.equals(mSecurityType, thatWifiInfo.mSecurityType)
+ && Objects.equals(mCurrentNetworkKey, thatWifiInfo.mCurrentNetworkKey);
}
@Override
@@ -1522,7 +1535,8 @@
mPasspointUniqueId,
mInformationElements,
mIsPrimary,
- mSecurityType);
+ mSecurityType,
+ mCurrentNetworkKey);
}
/**
@@ -1607,4 +1621,28 @@
return SECURITY_TYPE_UNKNOWN;
}
}
+
+ /**
+ * Set the network key for the current Wi-Fi network.
+ *
+ * Now we are using this identity to be a key when storing Wi-Fi data usage data.
+ * See: {@link WifiConfiguration#getNetworkKeyFromSecurityType(int)}.
+ *
+ * @param currentNetworkKey the network key of the current Wi-Fi network.
+ * @hide
+ */
+ public void setCurrentNetworkKey(@NonNull String currentNetworkKey) {
+ mCurrentNetworkKey = currentNetworkKey;
+ }
+
+ /**
+ * Returns the network key of the current Wi-Fi network.
+ *
+ * @hide
+ */
+ @SystemApi
+ @Nullable
+ public String getCurrentNetworkKey() {
+ return mCurrentNetworkKey;
+ }
}
diff --git a/framework/tests/src/android/net/wifi/WifiConfigurationTest.java b/framework/tests/src/android/net/wifi/WifiConfigurationTest.java
index 276d85f..80fb52f 100644
--- a/framework/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/framework/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -17,6 +17,7 @@
package android.net.wifi;
import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP;
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B;
import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE;
import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT;
import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OPEN;
@@ -29,6 +30,7 @@
import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WAPI_CERT;
import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WAPI_PSK;
import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WEP;
+import static android.net.wifi.WifiConfiguration.getSecurityTypeName;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -69,6 +71,18 @@
private static final int TEST_CARRIER_ID = 1234;
private static final int TEST_SUB_ID = 3;
private static final String TEST_PACKAGE_NAME = "google.com";
+ private static final int[] SECURITY_TYPES_EXCEPT_PASSPOINT = {
+ SECURITY_TYPE_OPEN,
+ SECURITY_TYPE_WEP,
+ SECURITY_TYPE_PSK,
+ SECURITY_TYPE_EAP,
+ SECURITY_TYPE_SAE,
+ SECURITY_TYPE_EAP_SUITE_B,
+ SECURITY_TYPE_OWE,
+ SECURITY_TYPE_WAPI_PSK,
+ SECURITY_TYPE_WAPI_CERT,
+ SECURITY_TYPE_EAP_WPA3_ENTERPRISE,
+ SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT};
@Before
public void setUp() {
@@ -930,6 +944,17 @@
}
}
+ private String createNetworkKey(String ssid, String keyMgmt, String providerName,
+ int carrierId, int subId, boolean isFromSuggestion) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(ssid).append(keyMgmt);
+ if (isFromSuggestion) {
+ sb.append("_").append(providerName).append('-')
+ .append(carrierId).append('-').append(subId);
+ }
+ return sb.toString();
+ }
+
/** Verify that adding security types works as expected. */
@Test
public void testAddSecurityTypes() {
@@ -1214,4 +1239,69 @@
List<SecurityParams> list = null;
config.setSecurityParams(list);
}
+
+ /**
+ * Verifies that getNetworkKeyFromSecurityType returns the correct String
+ * for networks of various different security types, the result should be stable.
+ *
+ * Note: DO NOT update the test if it happens failure! Fixed it is necessary, otherwise
+ * we will break Wi-Fi data usage functionality.
+ */
+ @Test
+ public void testGetNetworkKeyFromSecurityTypeString() {
+ WifiConfiguration config = new WifiConfiguration();
+ final String mSsid = "TestAP";
+ config.SSID = mSsid;
+ config.carrierId = TEST_CARRIER_ID;
+ config.subscriptionId = TEST_SUB_ID;
+ config.creatorName = TEST_PACKAGE_NAME;
+
+ for (int securityType : SECURITY_TYPES_EXCEPT_PASSPOINT) {
+ assertEquals(createNetworkKey(mSsid, getSecurityTypeName(securityType),
+ TEST_PACKAGE_NAME, TEST_CARRIER_ID, TEST_SUB_ID, false),
+ config.getNetworkKeyFromSecurityType(securityType));
+ }
+
+ // Test for passpoint configuration.
+ config.setPasspointUniqueId(TEST_PASSPOINT_UNIQUE_ID);
+ assertEquals(TEST_SUB_ID + "-" + TEST_PASSPOINT_UNIQUE_ID,
+ config.getNetworkKeyFromSecurityType(SECURITY_TYPE_PASSPOINT_R1_R2));
+ }
+
+ /**
+ * Verifies that getAllPersistableNetworkKeys returns the correct String set
+ * for networks of various different security types, the result should be stable.
+ *
+ * Note: DO NOT update the test if it happens failure! Fixed it is necessary, otherwise
+ * we will break Wi-Fi data usage functionality.
+ */
+ @Test
+ public void testGetAllPersistableNetworkKeysString() {
+ WifiConfiguration config = new WifiConfiguration();
+ final String mSsid = "TestAP";
+ config.SSID = mSsid;
+ config.carrierId = TEST_CARRIER_ID;
+ config.subscriptionId = TEST_SUB_ID;
+ config.creatorName = TEST_PACKAGE_NAME;
+ for (int securityType : SECURITY_TYPES_EXCEPT_PASSPOINT) {
+ config.setSecurityParams(securityType);
+ assertTrue(config.getAllPersistableNetworkKeys().contains(
+ createNetworkKey(mSsid, getSecurityTypeName(securityType),
+ TEST_PACKAGE_NAME, TEST_CARRIER_ID, TEST_SUB_ID, false)));
+ }
+
+ // Test with multi-security types
+ config.setSecurityParams(SECURITY_TYPE_PSK);
+ config.addSecurityParams(SECURITY_TYPE_SAE);
+ assertTrue(config.getAllPersistableNetworkKeys().contains(
+ createNetworkKey(mSsid, getSecurityTypeName(SECURITY_TYPE_PSK),
+ TEST_PACKAGE_NAME, TEST_CARRIER_ID, TEST_SUB_ID, false)));
+ assertTrue(config.getAllPersistableNetworkKeys().contains(
+ createNetworkKey(mSsid, getSecurityTypeName(SECURITY_TYPE_SAE),
+ TEST_PACKAGE_NAME, TEST_CARRIER_ID, TEST_SUB_ID, false)));
+ // Test for passpoint configuration.
+ config.setPasspointUniqueId(TEST_PASSPOINT_UNIQUE_ID);
+ assertTrue(config.getAllPersistableNetworkKeys().contains(
+ config.getNetworkKeyFromSecurityType(SECURITY_TYPE_PASSPOINT_R1_R2)));
+ }
}
diff --git a/framework/tests/src/android/net/wifi/WifiInfoTest.java b/framework/tests/src/android/net/wifi/WifiInfoTest.java
index 7b72fc7..1d40d9f 100644
--- a/framework/tests/src/android/net/wifi/WifiInfoTest.java
+++ b/framework/tests/src/android/net/wifi/WifiInfoTest.java
@@ -62,6 +62,7 @@
private static final int TEST_NETWORK_ID = 5;
private static final int TEST_NETWORK_ID2 = 6;
private static final int TEST_SUB_ID = 1;
+ private static final String TEST_NETWORK_KEY = "TestNetworkKey";
private WifiInfo makeWifiInfoForNoRedactions(
List<ScanResult.InformationElement> informationElements) {
@@ -182,6 +183,7 @@
info.setInformationElements(generateIes());
info.setIsPrimary(true);
info.setMacAddress(TEST_BSSID);
+ info.setCurrentNetworkKey(TEST_NETWORK_KEY);
return info;
}
@@ -212,6 +214,7 @@
assertEquals(TEST_SUB_ID, info.getSubscriptionId());
assertTrue(info.isPrimary());
}
+ assertEquals(null, info.getCurrentNetworkKey());
}
/**
@@ -324,6 +327,7 @@
info.setProviderFriendlyName(TEST_PROVIDER_NAME);
info.setInformationElements(generateIes());
info.setMacAddress(TEST_BSSID);
+ info.setCurrentNetworkKey(TEST_NETWORK_KEY);
return info;
}
@@ -336,6 +340,7 @@
assertNull(info.getPasspointProviderFriendlyName());
assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, info.getMacAddress());
assertNull(info.getInformationElements());
+ assertNull(info.getCurrentNetworkKey());
}
@Test
@@ -475,6 +480,7 @@
assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, wifiInfo.getSubscriptionId());
assertFalse(wifiInfo.isPrimary());
}
+ assertEquals(null, wifiInfo.getCurrentNetworkKey());
}
/**
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 3e22b60..40b71a4 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -4401,6 +4401,8 @@
mPasspointManager.requestVenueUrlAnqpElement(scanResult);
}
}
+ mWifiInfo.setCurrentNetworkKey(config.getNetworkKeyFromSecurityType(
+ mWifiInfo.getCurrentSecurityType()));
transitionTo(mL3ProvisioningState);
break;
}
@@ -4679,6 +4681,9 @@
mWifiInfo.setOsuAp(true);
}
mWifiInfo.setProviderFriendlyName(config.providerFriendlyName);
+ mWifiInfo.setCurrentNetworkKey(
+ config.getNetworkKeyFromSecurityType(
+ mWifiInfo.getCurrentSecurityType()));
}
}
sendNetworkChangeBroadcast(
diff --git a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
index f31b8c4..8e6bf77 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
@@ -1009,6 +1009,7 @@
}
assertEquals(Arrays.asList(scanResult.informationElements),
wifiInfo.getInformationElements());
+ assertNotNull(wifiInfo.getCurrentNetworkKey());
expectRegisterNetworkAgent((na) -> {
if (!mConnectedNetwork.carrierMerged) {
assertNull(na.subscriberId);