diff options
author | Peter Qiu <zqiu@google.com> | 2017-06-22 15:48:19 -0700 |
---|---|---|
committer | Peter Qiu <zqiu@google.com> | 2017-07-11 13:57:53 -0700 |
commit | 49357a30edf5786c8db4bad6f5dbe62545751cc6 (patch) | |
tree | 201d9fef949592bac0af6bdaa47c6b509daabc5b | |
parent | 26b97ef6a6d8e755e7db541afa84aacd807599d7 (diff) |
hotspot2: track number of providers that connected successfully
Add boolean field "hasEverConnected" to PasspointProvider to indicate
if the given provider had ever provided a successful network connection.
The added field is persisted to the config file.
Update the associated metric for the given provider after it was used
to successfully connect for the first time.
Note that PasspointManager#onPasspointNetworkConnected can be expanded
in the future to keep track of connected SSIDs for a given Passpoint
provider, as an additional input to the network selection algorithm.
Bug: 36358031
Test: frameworks/opt/net/wifi/tests/wifitests/runtests.sh
Test: manually verify the provider's "hasEverConnected" is set to true
in the config file after a success connection
Change-Id: I6ef4ec801f78f34ff2ca9df97ab06188e1cc0324
9 files changed, 157 insertions, 9 deletions
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java index 1128d3c77..d317f8386 100644 --- a/service/java/com/android/server/wifi/WifiMetrics.java +++ b/service/java/com/android/server/wifi/WifiMetrics.java @@ -1321,13 +1321,16 @@ public class WifiMetrics { } /** - * Update number of saved Passpoint profiles. + * Update metrics for saved Passpoint profiles. * * @param numSavedProfiles The number of saved Passpoint profiles + * @param numConnectedProfiles The number of saved Passpoint profiles that have ever resulted + * in a successful network connection */ - public void updateSavedPasspointProfiles(int numSavedProfiles) { + public void updateSavedPasspointProfiles(int numSavedProfiles, int numConnectedProfiles) { synchronized (mLock) { mWifiLogProto.numPasspointProviders = numSavedProfiles; + mWifiLogProto.numPasspointProvidersSuccessfullyConnected = numConnectedProfiles; } } diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 688a53cb8..6fd16e37b 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -4709,6 +4709,12 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss mWifiConfigManager.updateNetworkAfterConnect(mLastNetworkId); // On connect, reset wifiScoreReport mWifiScoreReport.reset(); + + // Notify PasspointManager of Passpoint network connected event. + WifiConfiguration currentNetwork = getCurrentWifiConfiguration(); + if (currentNetwork.isPasspoint()) { + mPasspointManager.onPasspointNetworkConnected(currentNetwork.FQDN); + } } } @@ -6985,7 +6991,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss */ public void updateWifiMetrics() { mWifiMetrics.updateSavedNetworks(mWifiConfigManager.getSavedNetworks()); - mWifiMetrics.updateSavedPasspointProfiles(mPasspointManager.getProviderConfigs().size()); + mPasspointManager.updateMetrics(); } /** diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointConfigStoreData.java b/service/java/com/android/server/wifi/hotspot2/PasspointConfigStoreData.java index 74a4760b4..38401d2ca 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointConfigStoreData.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointConfigStoreData.java @@ -66,6 +66,7 @@ public class PasspointConfigStoreData implements WifiConfigStore.StoreData { private static final String XML_TAG_CLIENT_PRIVATE_KEY_ALIAS = "ClientPrivateKeyAlias"; private static final String XML_TAG_PROVIDER_INDEX = "ProviderIndex"; + private static final String XML_TAG_HAS_EVER_CONNECTED = "HasEverConnected"; private final WifiKeyStore mKeyStore; private final SIMAccessor mSimAccessor; @@ -211,6 +212,7 @@ public class PasspointConfigStoreData implements WifiConfigStore.StoreData { provider.getClientCertificateAlias()); XmlUtil.writeNextValue(out, XML_TAG_CLIENT_PRIVATE_KEY_ALIAS, provider.getClientPrivateKeyAlias()); + XmlUtil.writeNextValue(out, XML_TAG_HAS_EVER_CONNECTED, provider.getHasEverConnected()); if (provider.getConfig() != null) { XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION); PasspointXmlUtils.serializePasspointConfiguration(out, provider.getConfig()); @@ -304,6 +306,7 @@ public class PasspointConfigStoreData implements WifiConfigStore.StoreData { String caCertificateAlias = null; String clientCertificateAlias = null; String clientPrivateKeyAlias = null; + boolean hasEverConnected = false; PasspointConfiguration config = null; while (XmlUtils.nextElementWithin(in, outerTagDepth)) { if (in.getAttributeValue(null, "name") != null) { @@ -326,6 +329,9 @@ public class PasspointConfigStoreData implements WifiConfigStore.StoreData { case XML_TAG_CLIENT_PRIVATE_KEY_ALIAS: clientPrivateKeyAlias = (String) value; break; + case XML_TAG_HAS_EVER_CONNECTED: + hasEverConnected = (boolean) value; + break; } } else { if (!TextUtils.equals(in.getName(), @@ -344,7 +350,8 @@ public class PasspointConfigStoreData implements WifiConfigStore.StoreData { throw new XmlPullParserException("Missing Passpoint configuration"); } return new PasspointProvider(config, mKeyStore, mSimAccessor, providerId, creatorUid, - caCertificateAlias, clientCertificateAlias, clientPrivateKeyAlias); + caCertificateAlias, clientCertificateAlias, clientPrivateKeyAlias, + hasEverConnected); } /** diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java index dad622136..5d79ba40a 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java @@ -536,6 +536,41 @@ public class PasspointManager { } /** + * Invoked when a Passpoint network was successfully connected based on the credentials + * provided by the given Passpoint provider (specified by its FQDN). + * + * @param fqdn The FQDN of the Passpoint provider + */ + public void onPasspointNetworkConnected(String fqdn) { + PasspointProvider provider = mProviders.get(fqdn); + if (provider == null) { + Log.e(TAG, "Passpoint network connected without provider: " + fqdn); + return; + } + + if (!provider.getHasEverConnected()) { + // First successful connection using this provider. + provider.setHasEverConnected(true); + } + } + + /** + * Update metrics related to installed Passpoint providers, this includes the number of + * installed providers and the number of those providers that results in a successful network + * connection. + */ + public void updateMetrics() { + int numProviders = mProviders.size(); + int numConnectedProviders = 0; + for (Map.Entry<String, PasspointProvider> entry : mProviders.entrySet()) { + if (entry.getValue().getHasEverConnected()) { + numConnectedProviders++; + } + } + mWifiMetrics.updateSavedPasspointProfiles(numProviders, numConnectedProviders); + } + + /** * Dump the current state of PasspointManager to the provided output stream. * * @param pw The output stream to write to @@ -595,7 +630,7 @@ public class PasspointManager { mSimAccessor, mProviderIndex++, wifiConfig.creatorUid, enterpriseConfig.getCaCertificateAlias(), enterpriseConfig.getClientCertificateAlias(), - enterpriseConfig.getClientCertificateAlias()); + enterpriseConfig.getClientCertificateAlias(), false); mProviders.put(passpointConfig.getHomeSp().getFqdn(), provider); return true; } diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java index c38098dac..c7943ed81 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java @@ -87,14 +87,17 @@ public class PasspointProvider { private final int mEAPMethodID; private final AuthParam mAuthParam; + private boolean mHasEverConnected; + public PasspointProvider(PasspointConfiguration config, WifiKeyStore keyStore, SIMAccessor simAccessor, long providerId, int creatorUid) { - this(config, keyStore, simAccessor, providerId, creatorUid, null, null, null); + this(config, keyStore, simAccessor, providerId, creatorUid, null, null, null, false); } public PasspointProvider(PasspointConfiguration config, WifiKeyStore keyStore, SIMAccessor simAccessor, long providerId, int creatorUid, String caCertificateAlias, - String clientCertificateAlias, String clientPrivateKeyAlias) { + String clientCertificateAlias, String clientPrivateKeyAlias, + boolean hasEverConnected) { // Maintain a copy of the configuration to avoid it being updated by others. mConfig = new PasspointConfiguration(config); mKeyStore = keyStore; @@ -103,6 +106,7 @@ public class PasspointProvider { mCaCertificateAlias = caCertificateAlias; mClientCertificateAlias = clientCertificateAlias; mClientPrivateKeyAlias = clientPrivateKeyAlias; + mHasEverConnected = hasEverConnected; // Setup EAP method and authentication parameter based on the credential. if (mConfig.getCredential().getUserCredential() != null) { @@ -150,6 +154,14 @@ public class PasspointProvider { return mCreatorUid; } + public boolean getHasEverConnected() { + return mHasEverConnected; + } + + public void setHasEverConnected(boolean hasEverConnected) { + mHasEverConnected = hasEverConnected; + } + /** * Install certificates and key based on current configuration. * Note: the certificates and keys in the configuration will get cleared once diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java index e58928bf5..e7216ce4a 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java @@ -295,7 +295,8 @@ public class WifiMetricsTest { */ public void setAndIncrementMetrics() throws Exception { mWifiMetrics.updateSavedNetworks(buildSavedNetworkList()); - mWifiMetrics.updateSavedPasspointProfiles(NUM_PASSPOINT_PROVIDERS); + mWifiMetrics.updateSavedPasspointProfiles(NUM_PASSPOINT_PROVIDERS, + NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED); mWifiMetrics.setIsLocationEnabled(TEST_VAL_IS_LOCATION_ENABLED); mWifiMetrics.setIsScanningAlwaysEnabled(IS_SCANNING_ALWAYS_ENABLED); @@ -592,6 +593,8 @@ public class WifiMetricsTest { mDeserializedWifiMetrics.numPasspointProviderUninstallation); assertEquals(NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS, mDeserializedWifiMetrics.numPasspointProviderUninstallSuccess); + assertEquals(NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED, + mDeserializedWifiMetrics.numPasspointProvidersSuccessfullyConnected); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigStoreDataTest.java index 8e808efcf..7e05c3d09 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigStoreDataTest.java @@ -60,6 +60,7 @@ public class PasspointConfigStoreDataTest { private static final String TEST_CLIENT_PRIVATE_KEY_ALIAS = "ClientPrivateKey"; private static final long TEST_PROVIDER_ID = 1; private static final int TEST_CREATOR_UID = 1234; + private static final boolean TEST_HAS_EVER_CONNECTED = true; @Mock WifiKeyStore mKeyStore; @Mock SIMAccessor mSimAccessor; @@ -238,7 +239,7 @@ public class PasspointConfigStoreDataTest { providerList.add(new PasspointProvider(createFullPasspointConfiguration(), mKeyStore, mSimAccessor, TEST_PROVIDER_ID, TEST_CREATOR_UID, TEST_CA_CERTIFICATE_ALIAS, TEST_CLIENT_CERTIFICATE_ALIAS, - TEST_CLIENT_PRIVATE_KEY_ALIAS)); + TEST_CLIENT_PRIVATE_KEY_ALIAS, TEST_HAS_EVER_CONNECTED)); // Serialize data for user store. when(mDataSource.getProviders()).thenReturn(providerList); diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java index a8dd831ed..01566c203 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java @@ -1215,4 +1215,62 @@ public class PasspointManagerTest { assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig)); } + + /** + * Verify that the provider's "hasEverConnected" flag will be set to true and the associated + * metric is updated after the provider was used to successfully connect to a Passpoint + * network for the first time. + * + * @throws Exception + */ + @Test + public void providerNetworkConnectedFirstTime() throws Exception { + PasspointProvider provider = addTestProvider(); + when(provider.getHasEverConnected()).thenReturn(false); + mManager.onPasspointNetworkConnected(TEST_FQDN); + verify(provider).setHasEverConnected(eq(true)); + } + + /** + * Verify that the provider's "hasEverConnected" flag the associated metric is not updated + * after the provider was used to successfully connect to a Passpoint network for non-first + * time. + * + * @throws Exception + */ + @Test + public void providerNetworkConnectedNotFirstTime() throws Exception { + PasspointProvider provider = addTestProvider(); + when(provider.getHasEverConnected()).thenReturn(true); + mManager.onPasspointNetworkConnected(TEST_FQDN); + verify(provider, never()).setHasEverConnected(anyBoolean()); + } + + /** + * Verify that the expected Passpoint metrics are updated when + * {@link PasspointManager#updateMetrics} is invoked. + * + * @throws Exception + */ + @Test + public void updateMetrics() throws Exception { + PasspointProvider provider = addTestProvider(); + + // Provider have not provided a successful network connection. + int expectedInstalledProviders = 1; + int expectedConnectedProviders = 0; + when(provider.getHasEverConnected()).thenReturn(false); + mManager.updateMetrics(); + verify(mWifiMetrics).updateSavedPasspointProfiles( + eq(expectedInstalledProviders), eq(expectedConnectedProviders)); + reset(provider); + reset(mWifiMetrics); + + // Provider have provided a successful network connection. + expectedConnectedProviders = 1; + when(provider.getHasEverConnected()).thenReturn(true); + mManager.updateMetrics(); + verify(mWifiMetrics).updateSavedPasspointProfiles( + eq(expectedInstalledProviders), eq(expectedConnectedProviders)); + } } diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java index 15f8471e0..9ee9fc6d5 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java @@ -963,4 +963,27 @@ public class PasspointProviderTest { assertFalse(mProvider.isSimCredential()); } + + /** + * Verify that hasEverConnected flag is set correctly using + * {@link PasspointProvider#setHasEverConnected}. + * + * @throws Exception + */ + @Test + public void setHasEverConnected() throws Exception { + PasspointConfiguration config = new PasspointConfiguration(); + HomeSp homeSp = new HomeSp(); + homeSp.setFqdn("test1"); + config.setHomeSp(homeSp); + Credential credential = new Credential(); + credential.setUserCredential(new Credential.UserCredential()); + config.setCredential(credential); + mProvider = createProvider(config); + verifyInstalledConfig(config, true); + + assertFalse(mProvider.getHasEverConnected()); + mProvider.setHasEverConnected(true); + assertTrue(mProvider.getHasEverConnected()); + } } |