diff options
19 files changed, 793 insertions, 215 deletions
diff --git a/service/java/com/android/server/wifi/IMSIParameter.java b/service/java/com/android/server/wifi/IMSIParameter.java index 5754fb132..45279864a 100644 --- a/service/java/com/android/server/wifi/IMSIParameter.java +++ b/service/java/com/android/server/wifi/IMSIParameter.java @@ -117,6 +117,15 @@ public class IMSIParameter { return mImsi.regionMatches(false, 0, mccMnc, 0, checkLength); } + /** + * If the IMSI is full length. + * + * @return true If the length of IMSI is full, false otherwise. + */ + public boolean isFullImsi() { + return !mPrefix; + } + @Override public boolean equals(Object thatObject) { if (this == thatObject) { diff --git a/service/java/com/android/server/wifi/SIMAccessor.java b/service/java/com/android/server/wifi/SIMAccessor.java deleted file mode 100644 index 13186f1e1..000000000 --- a/service/java/com/android/server/wifi/SIMAccessor.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.android.server.wifi; - -import android.content.Context; -import android.telephony.SubscriptionInfo; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; - -import java.util.ArrayList; -import java.util.List; - -public class SIMAccessor { - private final TelephonyManager mTelephonyManager; - private final SubscriptionManager mSubscriptionManager; - - public SIMAccessor(Context context) { - // TODO(b/132188983): Inject this using WifiInjector - mTelephonyManager = context.getSystemService(TelephonyManager.class); - // TODO(b/132188983): Inject this using WifiInjector - mSubscriptionManager = context.getSystemService(SubscriptionManager.class); - } - - public List<String> getMatchingImsis(IMSIParameter mccMnc) { - if (mccMnc == null) { - return null; - } - List<String> imsis = new ArrayList<>(); - for (SubscriptionInfo sub : mSubscriptionManager.getActiveSubscriptionInfoList()) { - String imsi = - mTelephonyManager.createForSubscriptionId(sub.getSubscriptionId()) - .getSubscriberId(); - if (imsi != null && mccMnc.matchesImsi(imsi)) { - imsis.add(imsi); - } - } - return imsis.isEmpty() ? null : imsis; - } -} diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index 683db73f6..35fd64c5e 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -134,7 +134,6 @@ public class WifiInjector { private final WifiPermissionsWrapper mWifiPermissionsWrapper; private final WifiPermissionsUtil mWifiPermissionsUtil; private final PasspointManager mPasspointManager; - private final SIMAccessor mSimAccessor; private HandlerThread mWifiAwareHandlerThread; private HandlerThread mRttHandlerThread; private HalDeviceManager mHalDeviceManager; @@ -300,11 +299,10 @@ public class WifiInjector { mWifiNetworkScoreCache, mWifiPermissionsUtil); mCarrierNetworkEvaluator = new CarrierNetworkEvaluator(mWifiConfigManager, mCarrierNetworkConfig, mConnectivityLocalLog, this); - mSimAccessor = new SIMAccessor(mContext); mPasspointManager = new PasspointManager(mContext, this, wifiHandler, mWifiNative, mWifiKeyStore, mClock, - mSimAccessor, new PasspointObjectFactory(), mWifiConfigManager, mWifiConfigStore, - mWifiMetrics, subscriptionManager); + new PasspointObjectFactory(), mWifiConfigManager, mWifiConfigStore, + mWifiMetrics, mTelephonyUtil); mPasspointNetworkEvaluator = new PasspointNetworkEvaluator( mPasspointManager, mWifiConfigManager, mConnectivityLocalLog, this, subscriptionManager); diff --git a/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java b/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java index bef7a9f9a..56836a4bb 100644 --- a/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java +++ b/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java @@ -16,6 +16,8 @@ package com.android.server.wifi.hotspot2; +import android.text.TextUtils; + import com.android.server.wifi.IMSIParameter; import com.android.server.wifi.hotspot2.anqp.CellularNetwork; import com.android.server.wifi.hotspot2.anqp.DomainNameElement; @@ -43,12 +45,12 @@ public class ANQPMatcher { * @param element The Domain Name ANQP element * @param fqdn The FQDN to compare against * @param imsiParam The IMSI parameter of the provider - * @param simImsiList The list of IMSI from the installed SIM cards that matched provider's + * @param simImsi The IMSI from the installed SIM cards that best matched provider's * IMSI parameter * @return true if a match is found */ public static boolean matchDomainName(DomainNameElement element, String fqdn, - IMSIParameter imsiParam, List<String> simImsiList) { + IMSIParameter imsiParam, String simImsi) { if (element == null) { return false; } @@ -60,7 +62,7 @@ public class ANQPMatcher { // Try to retrieve the MCC-MNC string from the domain (for 3GPP network domain) and // match against the provider's SIM credential. - if (matchMccMnc(Utils.getMccMnc(Utils.splitDomain(domain)), imsiParam, simImsiList)) { + if (matchMccMnc(Utils.getMccMnc(Utils.splitDomain(domain)), imsiParam, simImsi)) { return true; } } @@ -126,17 +128,17 @@ public class ANQPMatcher { * * @param element 3GPP Network ANQP element * @param imsiParam The IMSI parameter of the provider's SIM credential - * @param simImsiList The list of IMSI from the installed SIM cards that matched provider's + * @param simImsi The IMSI from the installed SIM cards that best matched provider's * IMSI parameter * @return true if a matched is found */ public static boolean matchThreeGPPNetwork(ThreeGPPNetworkElement element, - IMSIParameter imsiParam, List<String> simImsiList) { + IMSIParameter imsiParam, String simImsi) { if (element == null) { return false; } for (CellularNetwork network : element.getNetworks()) { - if (matchCellularNetwork(network, imsiParam, simImsiList)) { + if (matchCellularNetwork(network, imsiParam, simImsi)) { return true; } } @@ -220,17 +222,18 @@ public class ANQPMatcher { * * @param network The cellular network that contained list of PLMNs * @param imsiParam IMSI parameter of the provider - * @param simImsiList The list of IMSI from the installed SIM cards that matched provider's + * @param simImsi The IMSI from the installed SIM cards that best matched provider's * IMSI parameter * @return true if a match is found */ private static boolean matchCellularNetwork(CellularNetwork network, IMSIParameter imsiParam, - List<String> simImsiList) { + String simImsi) { for (String plmn : network.getPlmns()) { - if (matchMccMnc(plmn, imsiParam, simImsiList)) { + if (matchMccMnc(plmn, imsiParam, simImsi)) { return true; } } + return false; } @@ -239,27 +242,22 @@ public class ANQPMatcher { * * @param mccMnc The string containing MCC-MNC * @param imsiParam The IMSI parameter of the provider - * @param simImsiList The list of IMSI from the installed SIM cards that matched provider's + * @param simImsi The IMSI from the installed SIM cards that best matched provider's * IMSI parameter * @return true if a match is found */ private static boolean matchMccMnc(String mccMnc, IMSIParameter imsiParam, - List<String> simImsiList) { - if (imsiParam == null || simImsiList == null || mccMnc == null) { + String simImsi) { + if (imsiParam == null || TextUtils.isEmpty(simImsi) || mccMnc == null) { return false; } // Match against the IMSI parameter in the provider. if (!imsiParam.matchesMccMnc(mccMnc)) { return false; } - // Additional check for verifying the match with IMSIs from the SIM cards, since the IMSI + // Additional check for verifying the match with IMSI from the SIM card, since the IMSI // parameter might not contain the full 6-digit MCC MNC (e.g. IMSI parameter is an IMSI // prefix that contained less than 6-digit of numbers "12345*"). - for (String imsi : simImsiList) { - if (imsi.startsWith(mccMnc)) { - return true; - } - } - return false; + return simImsi.startsWith(mccMnc); } } diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java b/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java index 9e64417d0..1be093eb8 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java @@ -22,9 +22,9 @@ import android.text.TextUtils; import android.util.Log; import com.android.internal.util.XmlUtils; -import com.android.server.wifi.SIMAccessor; import com.android.server.wifi.WifiConfigStore; import com.android.server.wifi.WifiKeyStore; +import com.android.server.wifi.util.TelephonyUtil; import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtil; @@ -77,7 +77,7 @@ public class PasspointConfigUserStoreData implements WifiConfigStore.StoreData { private static final String XML_TAG_IS_FROM_SUGGESTION = "IsFromSuggestion"; private final WifiKeyStore mKeyStore; - private final SIMAccessor mSimAccessor; + private final TelephonyUtil mTelephonyUtil; private final DataSource mDataSource; /** @@ -99,10 +99,10 @@ public class PasspointConfigUserStoreData implements WifiConfigStore.StoreData { void setProviders(List<PasspointProvider> providers); } - PasspointConfigUserStoreData(WifiKeyStore keyStore, SIMAccessor simAccessor, + PasspointConfigUserStoreData(WifiKeyStore keyStore, TelephonyUtil telephonyUtil, DataSource dataSource) { mKeyStore = keyStore; - mSimAccessor = simAccessor; + mTelephonyUtil = telephonyUtil; mDataSource = dataSource; } @@ -343,7 +343,7 @@ public class PasspointConfigUserStoreData implements WifiConfigStore.StoreData { if (config == null) { throw new XmlPullParserException("Missing Passpoint configuration"); } - return new PasspointProvider(config, mKeyStore, mSimAccessor, providerId, creatorUid, + return new PasspointProvider(config, mKeyStore, mTelephonyUtil, providerId, creatorUid, packageName, isFromSuggestion, caCertificateAliases, clientPrivateKeyAndCertificateAlias, remediationCaCertificateAlias, hasEverConnected, shared); diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java index bce2f6c69..0d5f9043e 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java @@ -44,13 +44,11 @@ import android.os.Handler; import android.os.Looper; import android.os.Process; import android.os.UserHandle; -import android.telephony.SubscriptionManager; import android.text.TextUtils; import android.util.Log; import android.util.Pair; import com.android.server.wifi.Clock; -import com.android.server.wifi.SIMAccessor; import com.android.server.wifi.WifiConfigManager; import com.android.server.wifi.WifiConfigStore; import com.android.server.wifi.WifiInjector; @@ -62,6 +60,7 @@ import com.android.server.wifi.hotspot2.anqp.Constants; import com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement; import com.android.server.wifi.hotspot2.anqp.OsuProviderInfo; import com.android.server.wifi.util.InformationElementUtil; +import com.android.server.wifi.util.TelephonyUtil; import java.io.PrintWriter; import java.security.cert.X509Certificate; @@ -106,7 +105,6 @@ public class PasspointManager { private final PasspointEventHandler mPasspointEventHandler; private final WifiInjector mWifiInjector; private final Handler mHandler; - private final SIMAccessor mSimAccessor; private final WifiKeyStore mKeyStore; private final PasspointObjectFactory mObjectFactory; @@ -118,7 +116,7 @@ public class PasspointManager { private final WifiMetrics mWifiMetrics; private final PasspointProvisioner mPasspointProvisioner; private final AppOpsManager mAppOps; - private final SubscriptionManager mSubscriptionManager; + private final TelephonyUtil mTelephonyUtil; /** * Map of package name of an app to the app ops changed listener for the app. @@ -321,17 +319,16 @@ public class PasspointManager { } public PasspointManager(Context context, WifiInjector wifiInjector, Handler handler, - WifiNative wifiNative, WifiKeyStore keyStore, Clock clock, SIMAccessor simAccessor, + WifiNative wifiNative, WifiKeyStore keyStore, Clock clock, PasspointObjectFactory objectFactory, WifiConfigManager wifiConfigManager, WifiConfigStore wifiConfigStore, WifiMetrics wifiMetrics, - SubscriptionManager subscriptionManager) { + TelephonyUtil telephonyUtil) { mPasspointEventHandler = objectFactory.makePasspointEventHandler(wifiNative, new CallbackHandler(context)); mWifiInjector = wifiInjector; mHandler = handler; mKeyStore = keyStore; - mSimAccessor = simAccessor; mObjectFactory = objectFactory; mProviders = new HashMap<>(); mAnqpCache = objectFactory.makeAnqpCache(clock); @@ -340,9 +337,9 @@ public class PasspointManager { mWifiConfigManager = wifiConfigManager; mWifiMetrics = wifiMetrics; mProviderIndex = 0; - mSubscriptionManager = subscriptionManager; + mTelephonyUtil = telephonyUtil; wifiConfigStore.registerStoreData(objectFactory.makePasspointConfigUserStoreData( - mKeyStore, mSimAccessor, new UserDataSourceHandler())); + mKeyStore, mTelephonyUtil, new UserDataSourceHandler())); wifiConfigStore.registerStoreData(objectFactory.makePasspointConfigSharedStoreData( new SharedDataSourceHandler())); mPasspointProvisioner = objectFactory.makePasspointProvisioner(context, wifiNative, @@ -409,9 +406,10 @@ public class PasspointManager { } } + mTelephonyUtil.tryUpdateCarrierIdForPasspoint(config); // Create a provider and install the necessary certificates and keys. PasspointProvider newProvider = mObjectFactory.makePasspointProvider(config, mKeyStore, - mSimAccessor, mProviderIndex++, uid, packageName, isFromSuggestion); + mTelephonyUtil, mProviderIndex++, uid, packageName, isFromSuggestion); if (!newProvider.installCertsAndKeys()) { Log.e(TAG, "Failed to install certificates and keys to keystore"); @@ -588,8 +586,12 @@ public class PasspointManager { Log.d(TAG, "ANQP entry not found for: " + anqpKey); return allMatches; } + boolean anyProviderUpdated = false; for (Map.Entry<String, PasspointProvider> entry : mProviders.entrySet()) { PasspointProvider provider = entry.getValue(); + if (provider.tryUpdateCarrierId()) { + anyProviderUpdated = true; + } PasspointMatch matchStatus = provider.match(anqpEntry.getElements(), roamingConsortium); if (matchStatus == PasspointMatch.HomeProvider @@ -606,6 +608,9 @@ public class PasspointManager { allMatches.add(Pair.create(provider, matchStatus)); } } + if (anyProviderUpdated) { + mWifiConfigManager.saveToStore(true); + } if (allMatches.size() != 0) { for (Pair<PasspointProvider, PasspointMatch> match : allMatches) { Log.d(TAG, String.format("Matched %s to %s as %s", scanResult.SSID, @@ -955,7 +960,8 @@ public class PasspointManager { // Note that for legacy configuration, the alias for client private key is the same as the // alias for the client certificate. PasspointProvider provider = new PasspointProvider(passpointConfig, mKeyStore, - mSimAccessor, mProviderIndex++, wifiConfig.creatorUid, null, false, + mTelephonyUtil, + mProviderIndex++, wifiConfig.creatorUid, null, false, Arrays.asList(enterpriseConfig.getCaCertificateAlias()), enterpriseConfig.getClientCertificateAlias(), null, false, false); mProviders.put(passpointConfig.getHomeSp().getFqdn(), provider); diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java index 872889f81..3707e1c13 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java @@ -31,7 +31,6 @@ import com.android.server.wifi.WifiConfigManager; import com.android.server.wifi.WifiInjector; import com.android.server.wifi.WifiNetworkSelector; import com.android.server.wifi.util.ScanResultUtil; -import com.android.server.wifi.util.TelephonyUtil; import java.util.ArrayList; import java.util.List; @@ -118,11 +117,6 @@ public class PasspointNetworkEvaluator implements WifiNetworkSelector.NetworkEva Pair<PasspointProvider, PasspointMatch> bestProvider = mPasspointManager.matchProvider(scanResult); if (bestProvider != null) { - if (bestProvider.first.isSimCredential() - && !TelephonyUtil.isSimPresent(mSubscriptionManager)) { - // Skip providers backed by SIM credential when SIM is not present. - continue; - } candidateList.add(new PasspointNetworkCandidate( bestProvider.first, bestProvider.second, scanDetail)); } diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java b/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java index 94be270e2..8c1f68b92 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java @@ -21,10 +21,10 @@ import android.net.wifi.hotspot2.PasspointConfiguration; import com.android.org.conscrypt.TrustManagerImpl; import com.android.server.wifi.Clock; -import com.android.server.wifi.SIMAccessor; import com.android.server.wifi.WifiKeyStore; import com.android.server.wifi.WifiMetrics; import com.android.server.wifi.WifiNative; +import com.android.server.wifi.util.TelephonyUtil; import java.security.KeyStore; import java.security.NoSuchAlgorithmException; @@ -58,9 +58,9 @@ public class PasspointObjectFactory{ * @return {@link PasspointProvider} */ public PasspointProvider makePasspointProvider(PasspointConfiguration config, - WifiKeyStore keyStore, SIMAccessor simAccessor, long providerId, int creatorUid, + WifiKeyStore keyStore, TelephonyUtil telephonyUtil, long providerId, int creatorUid, String packageName, boolean isFromSuggestion) { - return new PasspointProvider(config, keyStore, simAccessor, providerId, creatorUid, + return new PasspointProvider(config, keyStore, telephonyUtil, providerId, creatorUid, packageName, isFromSuggestion); } @@ -68,13 +68,13 @@ public class PasspointObjectFactory{ * Create a {@link PasspointConfigUserStoreData} instance. * * @param keyStore Instance of {@link WifiKeyStore} - * @param simAccessor Instance of {@link SIMAccessor} + * @param telephonyUtil Instance of {@link TelephonyUtil} * @param dataSource Passpoint configuration data source * @return {@link PasspointConfigUserStoreData} */ public PasspointConfigUserStoreData makePasspointConfigUserStoreData(WifiKeyStore keyStore, - SIMAccessor simAccessor, PasspointConfigUserStoreData.DataSource dataSource) { - return new PasspointConfigUserStoreData(keyStore, simAccessor, dataSource); + TelephonyUtil telephonyUtil, PasspointConfigUserStoreData.DataSource dataSource) { + return new PasspointConfigUserStoreData(keyStore, telephonyUtil, dataSource); } /** diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java index 111048d2b..f9ef69eb8 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java @@ -25,13 +25,14 @@ import android.net.wifi.hotspot2.pps.Credential; import android.net.wifi.hotspot2.pps.Credential.SimCredential; import android.net.wifi.hotspot2.pps.Credential.UserCredential; import android.net.wifi.hotspot2.pps.HomeSp; +import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Base64; import android.util.Log; +import android.util.Pair; import com.android.internal.util.ArrayUtils; import com.android.server.wifi.IMSIParameter; -import com.android.server.wifi.SIMAccessor; import com.android.server.wifi.WifiKeyStore; import com.android.server.wifi.hotspot2.anqp.ANQPElement; import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType; @@ -42,6 +43,7 @@ import com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement; import com.android.server.wifi.hotspot2.anqp.eap.AuthParam; import com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth; import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium; +import com.android.server.wifi.util.TelephonyUtil; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; @@ -91,24 +93,26 @@ public class PasspointProvider { private final String mPackageName; private final IMSIParameter mImsiParameter; - private final List<String> mMatchingSIMImsiList; private final int mEAPMethodID; private final AuthParam mAuthParam; + private final TelephonyUtil mTelephonyUtil; + private int mBestGuessCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; private boolean mHasEverConnected; private boolean mIsShared; private boolean mIsFromSuggestion; + public PasspointProvider(PasspointConfiguration config, WifiKeyStore keyStore, - SIMAccessor simAccessor, long providerId, int creatorUid, String packageName, + TelephonyUtil telephonyUtil, long providerId, int creatorUid, String packageName, boolean isFromSuggestion) { - this(config, keyStore, simAccessor, providerId, creatorUid, packageName, isFromSuggestion, + this(config, keyStore, telephonyUtil, providerId, creatorUid, packageName, isFromSuggestion, null, null, null, false, false); } public PasspointProvider(PasspointConfiguration config, WifiKeyStore keyStore, - SIMAccessor simAccessor, long providerId, int creatorUid, String packageName, + TelephonyUtil telephonyUtil, long providerId, int creatorUid, String packageName, boolean isFromSuggestion, List<String> caCertificateAliases, String clientPrivateKeyAndCertificateAlias, String remediationCaCertificateAlias, @@ -125,6 +129,7 @@ public class PasspointProvider { mHasEverConnected = hasEverConnected; mIsShared = isShared; mIsFromSuggestion = isFromSuggestion; + mTelephonyUtil = telephonyUtil; // Setup EAP method and authentication parameter based on the credential. if (mConfig.getCredential().getUserCredential() != null) { @@ -132,18 +137,15 @@ public class PasspointProvider { mAuthParam = new NonEAPInnerAuth(NonEAPInnerAuth.getAuthTypeID( mConfig.getCredential().getUserCredential().getNonEapInnerMethod())); mImsiParameter = null; - mMatchingSIMImsiList = null; } else if (mConfig.getCredential().getCertCredential() != null) { mEAPMethodID = EAPConstants.EAP_TLS; mAuthParam = null; mImsiParameter = null; - mMatchingSIMImsiList = null; } else { mEAPMethodID = mConfig.getCredential().getSimCredential().getEapType(); mAuthParam = null; mImsiParameter = IMSIParameter.build( mConfig.getCredential().getSimCredential().getImsi()); - mMatchingSIMImsiList = simAccessor.getMatchingImsis(mImsiParameter); } } @@ -288,6 +290,34 @@ public class PasspointProvider { } /** + * Try to update the carrier ID according to the IMSI parameter of passpoint configuration. + * + * @return true if the carrier ID is updated, otherwise false. + */ + public boolean tryUpdateCarrierId() { + return mTelephonyUtil.tryUpdateCarrierIdForPasspoint(mConfig); + } + + private @Nullable String getMatchingSimImsi() { + String matchingSIMImsi = null; + if (mConfig.getCarrierId() != TelephonyManager.UNKNOWN_CARRIER_ID) { + matchingSIMImsi = mTelephonyUtil + .getMatchingImsi(mConfig.getCarrierId()); + } else { + // Get the IMSI and carrier ID of SIM card which match with the IMSI prefix from + // passpoint profile + Pair<String, Integer> imsiCarrierIdPair = mTelephonyUtil.getMatchingImsiCarrierId( + mConfig.getCredential().getSimCredential().getImsi()); + if (imsiCarrierIdPair != null) { + matchingSIMImsi = imsiCarrierIdPair.first; + mBestGuessCarrierId = imsiCarrierIdPair.second; + } + } + + return matchingSIMImsi; + } + + /** * Return the matching status with the given AP, based on the ANQP elements from the AP. * * @param anqpElements ANQP elements from the AP @@ -296,12 +326,23 @@ public class PasspointProvider { */ public PasspointMatch match(Map<ANQPElementType, ANQPElement> anqpElements, RoamingConsortium roamingConsortium) { - PasspointMatch providerMatch = matchProviderExceptFor3GPP(anqpElements, roamingConsortium); + + String matchingSimImsi = null; + if (mConfig.getCredential().getSimCredential() != null) { + matchingSimImsi = getMatchingSimImsi(); + if (TextUtils.isEmpty(matchingSimImsi)) { + Log.d(TAG, "No SIM card for this profile with SIM credential."); + return PasspointMatch.None; + } + } + + PasspointMatch providerMatch = matchProviderExceptFor3GPP( + anqpElements, roamingConsortium, matchingSimImsi); // 3GPP Network matching. if (providerMatch == PasspointMatch.None && ANQPMatcher.matchThreeGPPNetwork( (ThreeGPPNetworkElement) anqpElements.get(ANQPElementType.ANQP3GPPNetwork), - mImsiParameter, mMatchingSIMImsiList)) { + mImsiParameter, matchingSimImsi)) { return PasspointMatch.RoamingProvider; } @@ -353,6 +394,11 @@ public class PasspointProvider { wifiConfig.providerFriendlyName = mConfig.getHomeSp().getFriendlyName(); wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); + int carrierId = mConfig.getCarrierId(); + if (carrierId == TelephonyManager.UNKNOWN_CARRIER_ID) { + carrierId = mBestGuessCarrierId; + } + wifiConfig.carrierId = carrierId; // Set RSN only to tell wpa_supplicant that this network is for Passpoint. wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN); @@ -425,6 +471,7 @@ public class PasspointProvider { wifiConfig.roamingConsortiumIds, wifiConfig.roamingConsortiumIds.length)); } passpointConfig.setHomeSp(homeSp); + passpointConfig.setCarrierId(wifiConfig.carrierId); // Setup Credential. Credential credential = new Credential(); @@ -563,11 +610,11 @@ public class PasspointProvider { */ private PasspointMatch matchProviderExceptFor3GPP( Map<ANQPElementType, ANQPElement> anqpElements, - RoamingConsortium roamingConsortium) { + RoamingConsortium roamingConsortium, String matchingSIMImsi) { // Domain name matching. if (ANQPMatcher.matchDomainName( (DomainNameElement) anqpElements.get(ANQPElementType.ANQPDomName), - mConfig.getHomeSp().getFqdn(), mImsiParameter, mMatchingSIMImsiList)) { + mConfig.getHomeSp().getFqdn(), mImsiParameter, matchingSIMImsi)) { return PasspointMatch.HomeProvider; } diff --git a/service/java/com/android/server/wifi/util/TelephonyUtil.java b/service/java/com/android/server/wifi/util/TelephonyUtil.java index e9f0a4686..b1dda6dfb 100644 --- a/service/java/com/android/server/wifi/util/TelephonyUtil.java +++ b/service/java/com/android/server/wifi/util/TelephonyUtil.java @@ -19,6 +19,8 @@ package com.android.server.wifi.util; import android.annotation.NonNull; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiEnterpriseConfig; +import android.net.wifi.hotspot2.PasspointConfiguration; +import android.net.wifi.hotspot2.pps.Credential; import android.telephony.ImsiEncryptionInfo; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; @@ -29,6 +31,7 @@ import android.util.Log; import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.wifi.IMSIParameter; import com.android.server.wifi.WifiNative; import java.security.InvalidKeyException; @@ -37,7 +40,7 @@ import java.security.PublicKey; import java.util.HashMap; import java.util.List; -import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; @@ -99,23 +102,24 @@ public class TelephonyUtil { * @param config the instance of {@link WifiConfiguration} * @return the best match SubscriptionId */ - public int getBestMatchSubscriptionId(WifiConfiguration config) { + public int getBestMatchSubscriptionId(@NonNull WifiConfiguration config) { + if (config.isPasspoint()) { + return getMatchingSubId(config.carrierId); + } else { + return getBestMatchSubscriptionIdForEnterprise(config); + } + } + + private int getMatchingSubId(int carrierId) { List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList(); if (subInfoList == null || subInfoList.isEmpty()) { return SubscriptionManager.INVALID_SUBSCRIPTION_ID; } - // Legacy WifiConfiguration without carrier ID - if (config.carrierId == TelephonyManager.UNKNOWN_CARRIER_ID - && config.enterpriseConfig != null - && config.enterpriseConfig.requireSimCredential()) { - Log.d(TAG, "carrierId is not assigned, using the default data sub."); - return SubscriptionManager.getDefaultDataSubscriptionId(); - } int dataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); int matchSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; for (SubscriptionInfo subInfo : subInfoList) { - if (subInfo.getCarrierId() == config.carrierId) { + if (subInfo.getCarrierId() == carrierId) { matchSubId = subInfo.getSubscriptionId(); if (matchSubId == dataSubId) { // Priority of Data sub is higher than non data sub. @@ -123,10 +127,29 @@ public class TelephonyUtil { } } } - Log.d(TAG, "best match subscription id: " + matchSubId); + Log.d(TAG, "matching subId is " + matchSubId); return matchSubId; } + private int getBestMatchSubscriptionIdForEnterprise(WifiConfiguration config) { + if (config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { + return getMatchingSubId(config.carrierId); + } + // Legacy WifiConfiguration without carrier ID + if (config.enterpriseConfig == null + || !config.enterpriseConfig.requireSimCredential()) { + Log.w(TAG, "The legacy config is not using EAP-SIM."); + return SubscriptionManager.INVALID_SUBSCRIPTION_ID; + } + int dataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); + if (isSimPresent(dataSubId)) { + Log.d(TAG, "carrierId is not assigned, using the default data sub."); + return dataSubId; + } + Log.d(TAG, "data sim is not present."); + return SubscriptionManager.INVALID_SUBSCRIPTION_ID; + } + /** * Check if the specified SIM card is in the device. * @@ -751,36 +774,28 @@ public class TelephonyUtil { /** * Get the carrier type of current SIM. * - * @param tm {@link TelephonyManager} instance + * @param subId the subscription ID of SIM card. * @return carrier type of current active sim, {{@link #CARRIER_INVALID_TYPE}} if sim is not - * ready or {@code tm} is {@code null} + * ready. */ - public static int getCarrierType(@NonNull TelephonyManager tm) { - if (tm == null) { + private int getCarrierType(int subId) { + if (!SubscriptionManager.isValidSubscriptionId(subId)) { return CARRIER_INVALID_TYPE; } - TelephonyManager defaultDataTm = tm.createForSubscriptionId( - SubscriptionManager.getDefaultDataSubscriptionId()); + TelephonyManager specifiedTm = mTelephonyManager.createForSubscriptionId(subId); - if (defaultDataTm.getSimState() != TelephonyManager.SIM_STATE_READY) { + if (specifiedTm.getSimState() != TelephonyManager.SIM_STATE_READY) { return CARRIER_INVALID_TYPE; } // If two APIs return the same carrier ID, then is considered as MNO, otherwise MVNO - if (defaultDataTm.getCarrierIdFromSimMccMnc() == defaultDataTm.getSimCarrierId()) { + if (specifiedTm.getCarrierIdFromSimMccMnc() == specifiedTm.getSimCarrierId()) { return CARRIER_MNO_TYPE; } return CARRIER_MVNO_TYPE; } /** - * Returns true if at least one SIM is present on the device, false otherwise. - */ - public static boolean isSimPresent(@Nonnull SubscriptionManager sm) { - return !sm.getActiveSubscriptionInfoList().isEmpty(); - } - - /** * Decorates a pseudonym with the NAI realm, in case it wasn't provided by the server * * @param config The instance of WifiConfiguration @@ -832,4 +847,127 @@ public class TelephonyUtil { TelephonyManager specifiedTm = mTelephonyManager.createForSubscriptionId(subId); specifiedTm.resetCarrierKeysForImsiEncryption(); } + + /** + * Updates the carrier ID for passpoint configuration with SIM credential. + * + * @param config The instance of PasspointConfiguration. + * @return true if the carrier ID is updated, false otherwise + */ + public boolean tryUpdateCarrierIdForPasspoint(PasspointConfiguration config) { + if (config.getCarrierId() != TelephonyManager.UNKNOWN_CARRIER_ID) { + return false; + } + + Credential.SimCredential simCredential = config.getCredential().getSimCredential(); + if (simCredential == null) { + // carrier ID is not required. + return false; + } + + IMSIParameter imsiParameter = IMSIParameter.build(simCredential.getImsi()); + // If the IMSI is not full, the carrier ID can not be matched for sure, so it should + // be ignored. + if (imsiParameter == null || !imsiParameter.isFullImsi()) { + Log.d(TAG, "IMSI is not available or not full"); + return false; + } + List<SubscriptionInfo> infos = mSubscriptionManager.getActiveSubscriptionInfoList(); + if (infos == null) { + return false; + } + // Find the active matching SIM card with the full IMSI from passpoint profile. + for (SubscriptionInfo subInfo : infos) { + TelephonyManager specifiedTm = + mTelephonyManager.createForSubscriptionId(subInfo.getSubscriptionId()); + String imsi = specifiedTm.getSubscriberId(); + if (imsiParameter.matchesImsi(imsi)) { + config.setCarrierId(subInfo.getCarrierId()); + return true; + } + } + + return false; + } + + /** + * Get the IMSI and carrier ID of the SIM card which is matched with the given carrier ID. + * + * @param carrierId The carrier ID see {@link TelephonyManager.getSimCarrierId} + * @return null if there is no matching SIM card, otherwise the IMSI and carrier ID of the + * matching SIM card + */ + public @Nullable String getMatchingImsi(int carrierId) { + int subId = getMatchingSubId(carrierId); + if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + return mTelephonyManager.getSubscriberId(subId); + } + + Log.d(TAG, "no active SIM card to match the carrier ID."); + return null; + } + + /** + * Get the IMSI and carrier ID of the SIM card which is matched with the given IMSI + * (only prefix of IMSI - mccmnc*) from passpoint profile. + * + * @param imsiPrefix The IMSI parameter from passpoint profile. + * @return null if there is no matching SIM card, otherwise the IMSI and carrier ID of the + * matching SIM card + */ + public @Nullable Pair<String, Integer> getMatchingImsiCarrierId( + String imsiPrefix) { + IMSIParameter imsiParameter = IMSIParameter.build(imsiPrefix); + if (imsiParameter == null) { + return null; + } + List<SubscriptionInfo> infos = mSubscriptionManager.getActiveSubscriptionInfoList(); + if (infos == null) { + return null; + } + int dataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); + //Pair<IMSI, carrier ID> the IMSI and carrier ID of matched SIM card + Pair<String, Integer> matchedPair = null; + // matchedDataPair check if the data SIM is matched. + Pair<String, Integer> matchedDataPair = null; + // matchedMnoPair check if any matched SIM card is MNO. + Pair<String, Integer> matchedMnoPair = null; + + // Find the active matched SIM card with the priority order of Data MNO SIM, + // Nondata MNO SIM, Data MVNO SIM, Nondata MVNO SIM. + for (SubscriptionInfo subInfo : infos) { + TelephonyManager specifiedTm = mTelephonyManager.createForSubscriptionId( + subInfo.getSubscriptionId()); + String operatorNumeric = specifiedTm.getSimOperatorNumeric(); + if (operatorNumeric != null && imsiParameter.matchesMccMnc(operatorNumeric)) { + String curImsi = specifiedTm.getSubscriberId(); + if (TextUtils.isEmpty(curImsi)) { + continue; + } + matchedPair = new Pair<>(curImsi, subInfo.getCarrierId()); + if (subInfo.getSubscriptionId() == dataSubId) { + matchedDataPair = matchedPair; + if (getCarrierType(subInfo.getSubscriptionId()) == CARRIER_MNO_TYPE) { + Log.d(TAG, "MNO data is matched via IMSI."); + return matchedDataPair; + } + } + if (getCarrierType(subInfo.getSubscriptionId()) == CARRIER_MNO_TYPE) { + matchedMnoPair = matchedPair; + } + } + } + + if (matchedMnoPair != null) { + Log.d(TAG, "MNO sub is matched via IMSI."); + return matchedMnoPair; + } + + if (matchedDataPair != null) { + Log.d(TAG, "MVNO data sub is matched via IMSI."); + return matchedDataPair; + } + + return matchedPair; + } } diff --git a/tests/wifitests/Android.bp b/tests/wifitests/Android.bp index 341ab0982..5dd90c1fc 100644 --- a/tests/wifitests/Android.bp +++ b/tests/wifitests/Android.bp @@ -246,7 +246,6 @@ android_test { "com.android.server.wifi.ScoringParams.*", "com.android.server.wifi.SelfRecovery", "com.android.server.wifi.SelfRecovery.*", - "com.android.server.wifi.SIMAccessor", "com.android.server.wifi.SoftApManager", "com.android.server.wifi.SoftApManager.*", "com.android.server.wifi.SoftApModeConfiguration", diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java index 2b3491b31..6f59ac264 100644 --- a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java +++ b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java @@ -501,6 +501,8 @@ public class ClientModeImplTest extends WifiBaseTest { add(mock(SubscriptionInfo.class)); }}; when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subList); + when(mSubscriptionManager.getActiveSubscriptionIdList()) + .thenReturn(new int[]{DATA_SUBID}); TelephonyUtil tu = new TelephonyUtil(mTelephonyManager, mSubscriptionManager); mTelephonyUtil = spy(tu); @@ -1029,7 +1031,7 @@ public class ClientModeImplTest extends WifiBaseTest { /** * When the SIM card was removed, if the current wifi connection is using it, the connection - * should be disconnected. + * should be disconnected, otherwise, the connection shouldn't be impacted. */ @Test public void testResetSimWhenConnectedSimRemoved() throws Exception { diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java index edbd5cb7e..4ad2a251e 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java @@ -4568,6 +4568,8 @@ public class WifiConfigManagerTest extends WifiBaseTest { add(mock(SubscriptionInfo.class)); }}; when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subList); + when(mSubscriptionManager.getActiveSubscriptionIdList()) + .thenReturn(new int[]{DATA_SUBID}); WifiConfiguration network = WifiConfigurationTestUtil.createEapNetwork(); WifiConfiguration simNetwork = WifiConfigurationTestUtil.createEapNetwork( @@ -4624,6 +4626,8 @@ public class WifiConfigManagerTest extends WifiBaseTest { add(mock(SubscriptionInfo.class)); }}; when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subList); + when(mSubscriptionManager.getActiveSubscriptionIdList()) + .thenReturn(new int[]{DATA_SUBID}); WifiConfiguration peapSimNetwork = WifiConfigurationTestUtil.createEapNetwork( WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.SIM); diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPMatcherTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPMatcherTest.java index 6173ebd09..7a30ae069 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPMatcherTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPMatcherTest.java @@ -43,7 +43,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; @@ -85,11 +84,11 @@ public class ANQPMatcherTest extends WifiBaseTest { @Test public void matchDomainNameUsingIMSI() throws Exception { IMSIParameter imsiParam = new IMSIParameter("1234", true); - List<String> simImsiList = Arrays.asList(new String[] {"123457890", "123498723"}); + String simImsi = "123457890"; // 3GPP network domain with MCC=123 and MNC=456. String[] domains = new String[] {"wlan.mnc457.mcc123.3gppnetwork.org"}; DomainNameElement element = new DomainNameElement(Arrays.asList(domains)); - assertTrue(ANQPMatcher.matchDomainName(element, null, imsiParam, simImsiList)); + assertTrue(ANQPMatcher.matchDomainName(element, null, imsiParam, simImsi)); } /** @@ -304,46 +303,46 @@ public class ANQPMatcherTest extends WifiBaseTest { @Test public void matchThreeGPPNetworkWithNullElement() throws Exception { IMSIParameter imsiParam = new IMSIParameter("1234", true); - List<String> simImsiList = Arrays.asList(new String[] {"123456789", "123498723"}); - assertFalse(ANQPMatcher.matchThreeGPPNetwork(null, imsiParam, simImsiList)); + String simImsi = "123456789"; + assertFalse(ANQPMatcher.matchThreeGPPNetwork(null, imsiParam, simImsi)); } /** * Verify that 3GPP network will succeed when the given 3GPP Network ANQP element contained - * a MCC-MNC that matches the both IMSI parameter and an IMSI from the IMSI list. + * a MCC-MNC that matches the both IMSI parameter and a SIM IMSI. * * @throws Exception */ @Test public void matchThreeGPPNetwork() throws Exception { IMSIParameter imsiParam = new IMSIParameter("1234", true); - List<String> simImsiList = Arrays.asList(new String[] {"123456789", "123498723"}); + String simImsi = "123456789"; CellularNetwork network = new CellularNetwork(Arrays.asList(new String[] {"123456"})); ThreeGPPNetworkElement element = new ThreeGPPNetworkElement(Arrays.asList(new CellularNetwork[] {network})); // The MCC-MNC provided in 3GPP Network ANQP element matches both IMSI parameter // and an IMSI from the installed SIM card. - assertTrue(ANQPMatcher.matchThreeGPPNetwork(element, imsiParam, simImsiList)); + assertTrue(ANQPMatcher.matchThreeGPPNetwork(element, imsiParam, simImsi)); } /** * Verify that 3GPP network will failed when the given 3GPP Network ANQP element contained - * a MCC-MNC that match the IMSI parameter but not the IMSI list. + * a MCC-MNC that match the IMSI parameter but not the SIM IMSI. * * @throws Exception */ @Test public void matchThreeGPPNetworkWithoutSimImsiMatch() throws Exception { IMSIParameter imsiParam = new IMSIParameter("1234", true); - List<String> simImsiList = Arrays.asList(new String[] {"123457890", "123498723"}); + String simImsi = "123457890"; CellularNetwork network = new CellularNetwork(Arrays.asList(new String[] {"123456"})); ThreeGPPNetworkElement element = new ThreeGPPNetworkElement(Arrays.asList(new CellularNetwork[] {network})); // The MCC-MNC provided in 3GPP Network ANQP element doesn't match any of the IMSIs // from the installed SIM card. - assertFalse(ANQPMatcher.matchThreeGPPNetwork(element, imsiParam, simImsiList)); + assertFalse(ANQPMatcher.matchThreeGPPNetwork(element, imsiParam, simImsi)); } /** @@ -355,13 +354,13 @@ public class ANQPMatcherTest extends WifiBaseTest { @Test public void matchThreeGPPNetworkWithImsiParamMismatch() throws Exception { IMSIParameter imsiParam = new IMSIParameter("1234", true); - List<String> simImsiList = Arrays.asList(new String[] {"123457890", "123498723"}); + String simImsi = "123457890"; CellularNetwork network = new CellularNetwork(Arrays.asList(new String[] {"123356"})); ThreeGPPNetworkElement element = new ThreeGPPNetworkElement(Arrays.asList(new CellularNetwork[] {network})); // The MCC-MNC provided in 3GPP Network ANQP element doesn't match the IMSI parameter. - assertFalse(ANQPMatcher.matchThreeGPPNetwork(element, imsiParam, simImsiList)); + assertFalse(ANQPMatcher.matchThreeGPPNetwork(element, imsiParam, simImsi)); } /** @@ -372,10 +371,10 @@ public class ANQPMatcherTest extends WifiBaseTest { @Test public void verifyInvalidDomain() throws Exception { IMSIParameter imsiParam = new IMSIParameter("1234", true); - List<String> simImsiList = Arrays.asList(new String[] {"123457890", "123498723"}); + String simImsi = "123457890"; // 3GPP network domain with MCC=123 and MNC=456. String[] domains = new String[] {"wlan.mnc457.mccI23.3gppnetwork.org"}; DomainNameElement element = new DomainNameElement(Arrays.asList(domains)); - assertFalse(ANQPMatcher.matchDomainName(element, null, imsiParam, simImsiList)); + assertFalse(ANQPMatcher.matchDomainName(element, null, imsiParam, simImsi)); } } diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java index 5a30d7164..18f6bf5ce 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java @@ -29,10 +29,10 @@ import android.util.Xml; import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.SIMAccessor; import com.android.server.wifi.WifiBaseTest; import com.android.server.wifi.WifiConfigStore; import com.android.server.wifi.WifiKeyStore; +import com.android.server.wifi.util.TelephonyUtil; import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; @@ -71,7 +71,7 @@ public class PasspointConfigUserStoreDataTest extends WifiBaseTest { private static final boolean TEST_SHARED = false; @Mock WifiKeyStore mKeyStore; - @Mock SIMAccessor mSimAccessor; + @Mock TelephonyUtil mTelephonyUtil; @Mock PasspointConfigUserStoreData.DataSource mDataSource; PasspointConfigUserStoreData mConfigStoreData; @@ -79,7 +79,7 @@ public class PasspointConfigUserStoreDataTest extends WifiBaseTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mConfigStoreData = new PasspointConfigUserStoreData(mKeyStore, mSimAccessor, mDataSource); + mConfigStoreData = new PasspointConfigUserStoreData(mKeyStore, mTelephonyUtil, mDataSource); } /** @@ -245,12 +245,12 @@ public class PasspointConfigUserStoreDataTest extends WifiBaseTest { // Setup expected data. List<PasspointProvider> providerList = new ArrayList<>(); providerList.add(new PasspointProvider(createFullPasspointConfiguration(), - mKeyStore, mSimAccessor, TEST_PROVIDER_ID, TEST_CREATOR_UID, TEST_CREATOR_PACKAGE, + mKeyStore, mTelephonyUtil, TEST_PROVIDER_ID, TEST_CREATOR_UID, TEST_CREATOR_PACKAGE, false, Arrays.asList(TEST_CA_CERTIFICATE_ALIAS), TEST_CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, null, TEST_HAS_EVER_CONNECTED, TEST_SHARED)); - providerList.add(new PasspointProvider(createFullPasspointConfiguration(), - mKeyStore, mSimAccessor, TEST_PROVIDER_ID_2, TEST_CREATOR_UID, TEST_CREATOR_PACKAGE, + providerList.add(new PasspointProvider(createFullPasspointConfiguration(), mKeyStore, + mTelephonyUtil, TEST_PROVIDER_ID_2, TEST_CREATOR_UID, TEST_CREATOR_PACKAGE, true, Arrays.asList(TEST_CA_CERTIFICATE_ALIAS, TEST_CA_CERTIFICATE_ALIAS_2), TEST_CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, TEST_REMEDIATION_CA_CERTIFICATE_ALIAS, TEST_HAS_EVER_CONNECTED, TEST_SHARED)); 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 447d8b13b..ccfb1f0d1 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java @@ -42,12 +42,15 @@ import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyLong; import static org.mockito.Mockito.anyMap; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -73,7 +76,9 @@ import android.os.Handler; import android.os.Looper; import android.os.UserHandle; import android.os.test.TestLooper; +import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; import android.util.Base64; import android.util.Pair; @@ -82,8 +87,6 @@ import androidx.test.filters.SmallTest; import com.android.server.wifi.ClientModeImpl; import com.android.server.wifi.Clock; import com.android.server.wifi.FakeKeys; -import com.android.server.wifi.IMSIParameter; -import com.android.server.wifi.SIMAccessor; import com.android.server.wifi.WifiBaseTest; import com.android.server.wifi.WifiConfigManager; import com.android.server.wifi.WifiConfigStore; @@ -101,6 +104,7 @@ import com.android.server.wifi.hotspot2.anqp.I18Name; import com.android.server.wifi.hotspot2.anqp.OsuProviderInfo; import com.android.server.wifi.util.InformationElementUtil; import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium; +import com.android.server.wifi.util.TelephonyUtil; import org.junit.Before; import org.junit.Test; @@ -111,6 +115,7 @@ import org.mockito.MockitoSession; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import java.security.KeyStore; +import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; @@ -137,7 +142,9 @@ public class PasspointManagerTest extends WifiBaseTest { private static final String TEST_FRIENDLY_NAME2 = "second friendly name"; private static final String TEST_REALM = "realm.test.com"; private static final String TEST_IMSI = "123456*"; - private static final IMSIParameter TEST_IMSI_PARAM = IMSIParameter.build(TEST_IMSI); + private static final String FULL_IMSI = "123456789123456"; + private static final int TEST_CARRIER_ID = 10; + private static final int TEST_SUBID = 1; private static final long TEST_BSSID = 0x112233445566L; private static final String TEST_SSID = "TestSSID"; @@ -165,7 +172,6 @@ public class PasspointManagerTest extends WifiBaseTest { @Mock WifiNative mWifiNative; @Mock WifiKeyStore mWifiKeyStore; @Mock Clock mClock; - @Mock SIMAccessor mSimAccessor; @Mock PasspointObjectFactory mObjectFactory; @Mock PasspointEventHandler.Callbacks mCallbacks; @Mock AnqpCache mAnqpCache; @@ -185,6 +191,7 @@ public class PasspointManagerTest extends WifiBaseTest { @Mock AppOpsManager mAppOpsManager; @Mock WifiInjector mWifiInjector; @Mock ClientModeImpl mClientModeImpl; + @Mock TelephonyManager mTelephonyManager; @Mock SubscriptionManager mSubscriptionManager; @Mock WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; @@ -193,6 +200,7 @@ public class PasspointManagerTest extends WifiBaseTest { PasspointManager mManager; ArgumentCaptor<AppOpsManager.OnOpChangedListener> mAppOpChangedListenerCaptor = ArgumentCaptor.forClass(AppOpsManager.OnOpChangedListener.class); + TelephonyUtil mTelephonyUtil; /** Sets up test. */ @Before @@ -215,11 +223,12 @@ public class PasspointManagerTest extends WifiBaseTest { when(mWifiInjector.getClientModeImpl()).thenReturn(mClientModeImpl); when(mWifiInjector.getWifiNetworkSuggestionsManager()) .thenReturn(mWifiNetworkSuggestionsManager); + mTelephonyUtil = new TelephonyUtil(mTelephonyManager, mSubscriptionManager); mLooper = new TestLooper(); mHandler = new Handler(mLooper.getLooper()); mManager = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative, - mWifiKeyStore, mClock, mSimAccessor, mObjectFactory, mWifiConfigManager, - mWifiConfigStore, mWifiMetrics, mSubscriptionManager); + mWifiKeyStore, mClock, mObjectFactory, mWifiConfigManager, + mWifiConfigStore, mWifiMetrics, mTelephonyUtil); ArgumentCaptor<PasspointEventHandler.Callbacks> callbacks = ArgumentCaptor.forClass(PasspointEventHandler.Callbacks.class); verify(mObjectFactory).makePasspointEventHandler(any(WifiNative.class), @@ -230,7 +239,7 @@ public class PasspointManagerTest extends WifiBaseTest { ArgumentCaptor<PasspointConfigUserStoreData.DataSource> userDataSource = ArgumentCaptor.forClass(PasspointConfigUserStoreData.DataSource.class); verify(mObjectFactory).makePasspointConfigUserStoreData( - any(WifiKeyStore.class), any(SIMAccessor.class), userDataSource.capture()); + any(WifiKeyStore.class), any(TelephonyUtil.class), userDataSource.capture()); mCallbacks = callbacks.getValue(); mSharedDataSource = sharedDataSource.getValue(); mUserDataSource = userDataSource.getValue(); @@ -368,7 +377,7 @@ public class PasspointManagerTest extends WifiBaseTest { PasspointConfiguration config = createTestConfigWithUserCredential(fqdn, friendlyName); PasspointProvider provider = createMockProvider(config, wifiConfig); when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(false))).thenReturn(provider); when(provider.getPackageName()).thenReturn(packageName); assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, false)); @@ -609,7 +618,7 @@ public class PasspointManagerTest extends WifiBaseTest { PasspointProvider provider = createMockProvider(config); when(provider.getPackageName()).thenReturn(TEST_PACKAGE); when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(false))).thenReturn(provider); assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, false)); verifyInstalledConfig(config); @@ -656,7 +665,7 @@ public class PasspointManagerTest extends WifiBaseTest { TEST_REALM); PasspointProvider provider = createMockProvider(config); when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(false))).thenReturn(provider); assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, false)); verifyInstalledConfig(config); @@ -690,6 +699,47 @@ public class PasspointManagerTest extends WifiBaseTest { } /** + * Verify that if the passpoint profile has full IMSI, the carrier ID should be updated when + * the matched SIM card is present. + * @throws Exception + */ + @Test + public void addProviderWithValidFullImsiOfSimCredential() throws Exception { + PasspointConfiguration config = + createTestConfigWithSimCredential(TEST_FQDN, FULL_IMSI, TEST_REALM); + X509Certificate[] certArr = new X509Certificate[] {FakeKeys.CA_CERT0}; + config.getCredential().setCaCertificates(certArr); + SubscriptionInfo subInfo = mock(SubscriptionInfo.class); + when(subInfo.getSubscriptionId()).thenReturn(TEST_SUBID); + when(subInfo.getCarrierId()).thenReturn(TEST_CARRIER_ID); + TelephonyManager specifiedTm = mock(TelephonyManager.class); + when(mTelephonyManager.createForSubscriptionId(eq(TEST_SUBID))).thenReturn(specifiedTm); + when(specifiedTm.getSubscriberId()).thenReturn(FULL_IMSI); + List<SubscriptionInfo> subInfoList = new ArrayList<>() {{ + add(subInfo); + }}; + when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subInfoList); + doNothing().when(mCertVerifier).verifyCaCert(any(X509Certificate.class)); + when(mWifiKeyStore.putCaCertInKeyStore(any(String.class), any(Certificate.class))) + .thenReturn(true); + PasspointObjectFactory spyFactory = spy(new PasspointObjectFactory()); + doReturn(mCertVerifier).when(spyFactory).makeCertificateVerifier(); + PasspointManager ut = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative, + mWifiKeyStore, mClock, spyFactory, mWifiConfigManager, + mWifiConfigStore, mWifiMetrics, mTelephonyUtil); + + assertTrue(ut.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, true)); + + assertEquals(TEST_CARRIER_ID, config.getCarrierId()); + List<String> fqdnList = new ArrayList<>(){{ + add(TEST_FQDN); + }}; + assertEquals(TEST_CARRIER_ID, + ut.getWifiConfigsForPasspointProfiles(fqdnList).get(0).carrierId); + + } + + /** * Verify that adding a user saved provider with the same base domain as the existing provider * will succeed, and verify that the existing provider is replaced by the new provider with * the new configuration. @@ -703,7 +753,7 @@ public class PasspointManagerTest extends WifiBaseTest { TEST_REALM); PasspointProvider origProvider = createMockProvider(origConfig); when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(false))).thenReturn(origProvider); assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE, false)); verifyInstalledConfig(origConfig); @@ -725,7 +775,7 @@ public class PasspointManagerTest extends WifiBaseTest { TEST_FRIENDLY_NAME); PasspointProvider newProvider = createMockProvider(newConfig); when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(false))).thenReturn(newProvider); assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE, false)); verifyInstalledConfig(newConfig); @@ -755,7 +805,7 @@ public class PasspointManagerTest extends WifiBaseTest { PasspointProvider provider = mock(PasspointProvider.class); when(provider.installCertsAndKeys()).thenReturn(false); when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(false))) + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(false))) .thenReturn(provider); assertFalse(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, false)); verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); @@ -791,7 +841,7 @@ public class PasspointManagerTest extends WifiBaseTest { config.setUpdateIdentifier(1); PasspointProvider provider = createMockProvider(config); when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(false))).thenReturn(provider); assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, false)); verify(mCertVerifier, never()).verifyCaCert(any(X509Certificate.class)); @@ -932,6 +982,39 @@ public class PasspointManagerTest extends WifiBaseTest { } /** + * Verify that if the Carrier ID is updated during match, the config should be persisted. + */ + @Test + public void getAllMatchingProvidersUpdatedConfigWithFullImsiSimCredential() { + // static mocking + MockitoSession session = + com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic( + InformationElementUtil.class).startMocking(); + try { + PasspointProvider provider = addTestProvider(TEST_FQDN + 0, TEST_FRIENDLY_NAME, + TEST_PACKAGE); + when(provider.tryUpdateCarrierId()).thenReturn(true); + reset(mWifiConfigManager); + + ANQPData entry = new ANQPData(mClock, null); + InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa(); + vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID2; + + when(mAnqpCache.getEntry(TEST_ANQP_KEY2)).thenReturn(entry); + when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa); + when(provider.match(anyMap(), isNull())) + .thenReturn(PasspointMatch.HomeProvider); + + List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = + mManager.getAllMatchedProviders(createTestScanResult()); + + verify(mWifiConfigManager).saveToStore(eq(true)); + + } finally { + session.finishMocking(); + } + } + /** * Verify that an expected map of FQDN and a list of ScanResult will be returned when provided * scanResults are matched to installed Passpoint profiles. */ @@ -1273,7 +1356,7 @@ public class PasspointManagerTest extends WifiBaseTest { PasspointProvider provider = createMockProvider(config); // Verify the provider ID used to create the new provider. when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mSimAccessor), eq(providerIndex), eq(TEST_CREATOR_UID), + eq(mTelephonyUtil), eq(providerIndex), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(false))).thenReturn(provider); assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, false)); @@ -1625,7 +1708,7 @@ public class PasspointManagerTest extends WifiBaseTest { TEST_REALM); PasspointProvider provider = createMockProvider(config); when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(false))).thenReturn(provider); assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, false)); verifyInstalledConfig(config); @@ -1667,7 +1750,7 @@ public class PasspointManagerTest extends WifiBaseTest { when(provider.getPackageName()).thenReturn(TEST_PACKAGE); when(provider.isFromSuggestion()).thenReturn(true); when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(true))).thenReturn(provider); assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, true)); verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); @@ -1736,7 +1819,7 @@ public class PasspointManagerTest extends WifiBaseTest { PasspointProvider origProvider = createMockProvider(origConfig); when(origProvider.getPackageName()).thenReturn(TEST_PACKAGE); when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(true))).thenReturn(origProvider); assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE, true)); verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); @@ -1770,7 +1853,7 @@ public class PasspointManagerTest extends WifiBaseTest { when(newProvider.isFromSuggestion()).thenReturn(true); when(newProvider.getPackageName()).thenReturn(TEST_PACKAGE); when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(true))).thenReturn(newProvider); assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE, true)); verify(mWifiConfigManager).removePasspointConfiguredNetwork( @@ -1801,7 +1884,7 @@ public class PasspointManagerTest extends WifiBaseTest { PasspointProvider origProvider = createMockProvider(origConfig); when(origProvider.getPackageName()).thenReturn(TEST_PACKAGE); when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(true))).thenReturn(origProvider); assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE, true)); verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); @@ -1821,7 +1904,7 @@ public class PasspointManagerTest extends WifiBaseTest { TEST_FRIENDLY_NAME); PasspointProvider newProvider = createMockProvider(newConfig); when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(false))).thenReturn(newProvider); assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE, false)); verify(mWifiConfigManager).removePasspointConfiguredNetwork( @@ -1852,7 +1935,7 @@ public class PasspointManagerTest extends WifiBaseTest { PasspointProvider origProvider = createMockProvider(origConfig); when(origProvider.getPackageName()).thenReturn(TEST_PACKAGE); when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(false))).thenReturn(origProvider); assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE, false)); verifyInstalledConfig(origConfig); @@ -1875,7 +1958,7 @@ public class PasspointManagerTest extends WifiBaseTest { when(newProvider.isFromSuggestion()).thenReturn(true); when(newProvider.getPackageName()).thenReturn(TEST_PACKAGE1); when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore), - eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE1), + eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE1), eq(true))).thenReturn(newProvider); assertFalse(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE1, true)); verify(mWifiConfigManager, never()).removePasspointConfiguredNetwork( diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java index d5cdd5a96..96a8aac3d 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java @@ -368,34 +368,6 @@ public class PasspointNetworkEvaluatorTest { } /** - * Verify that null will be returned when matching a SIM credential provider without SIM - * card installed. - * - * @throws Exception - */ - @Test - public void evaluateScanMatchingSIMProviderWithoutSIMCard() throws Exception { - // Setup ScanDetail and match providers. - List<ScanDetail> scanDetails = Arrays.asList(new ScanDetail[] { - generateScanDetail(TEST_SSID1, TEST_BSSID1)}); - PasspointProvider testProvider = mock(PasspointProvider.class); - Pair<PasspointProvider, PasspointMatch> homeProvider = Pair.create( - testProvider, PasspointMatch.HomeProvider); - - when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); - when(testProvider.isSimCredential()).thenReturn(true); - // SIM is absent - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(Collections.emptyList()); - - assertEquals(null, mEvaluator.evaluateNetworks( - scanDetails, null, null, false, false, mOnConnectableListener)); - - verify(mOnConnectableListener, never()).onConnectable(any(), any(), anyInt()); - verify(testProvider, never()).getWifiConfig(); - } - - /** * Verify that anonymous identity is empty when matching a SIM credential provider with a * network that supports encrypted IMSI and anonymous identity. The anonymous identity will be * populated with {@code anonymous@<realm>} by ClientModeImpl's handling of the 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 beddb2199..9391abb3f 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java @@ -19,6 +19,7 @@ package com.android.server.wifi.hotspot2; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; @@ -32,13 +33,12 @@ import android.net.wifi.hotspot2.pps.HomeSp; import android.net.wifi.hotspot2.pps.UpdateParameter; import android.text.TextUtils; import android.util.Base64; +import android.util.Pair; import androidx.test.filters.SmallTest; import com.android.internal.util.ArrayUtils; import com.android.server.wifi.FakeKeys; -import com.android.server.wifi.IMSIParameter; -import com.android.server.wifi.SIMAccessor; import com.android.server.wifi.WifiBaseTest; import com.android.server.wifi.WifiKeyStore; import com.android.server.wifi.hotspot2.anqp.ANQPElement; @@ -53,6 +53,7 @@ import com.android.server.wifi.hotspot2.anqp.eap.AuthParam; import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod; import com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth; import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium; +import com.android.server.wifi.util.TelephonyUtil; import org.junit.Before; import org.junit.Test; @@ -107,6 +108,7 @@ public class PasspointProviderTest extends WifiBaseTest { private static final int TEST_EAP_TYPE = WifiEnterpriseConfig.Eap.SIM; private static final int TEST_SIM_CREDENTIAL_TYPE = EAPConstants.EAP_SIM; private static final String TEST_IMSI = "1234567890"; + private static final int VALID_CARRIER_ID = 1; private enum CredentialType { USER, @@ -115,7 +117,7 @@ public class PasspointProviderTest extends WifiBaseTest { } @Mock WifiKeyStore mKeyStore; - @Mock SIMAccessor mSimAccessor; + @Mock TelephonyUtil mTelephonyUtil; @Mock RoamingConsortium mRoamingConsortium; PasspointProvider mProvider; X509Certificate mRemediationCaCertificate; @@ -149,7 +151,7 @@ public class PasspointProviderTest extends WifiBaseTest { * @return {@link com.android.server.wifi.hotspot2.PasspointProvider} */ private PasspointProvider createProvider(PasspointConfiguration config) { - return new PasspointProvider(config, mKeyStore, mSimAccessor, PROVIDER_ID, CREATOR_UID, + return new PasspointProvider(config, mKeyStore, mTelephonyUtil, PROVIDER_ID, CREATOR_UID, CREATOR_PACKAGE, false); } @@ -691,8 +693,8 @@ public class PasspointProviderTest extends WifiBaseTest { // Setup test provider. PasspointConfiguration config = generateTestPasspointConfiguration( CredentialType.SIM, false); - when(mSimAccessor.getMatchingImsis(new IMSIParameter(TEST_IMSI, false))) - .thenReturn(Arrays.asList(new String[] {TEST_IMSI})); + when(mTelephonyUtil.getMatchingImsiCarrierId(TEST_IMSI)) + .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID)); mProvider = createProvider(config); // Setup Domain Name ANQP element. @@ -716,8 +718,8 @@ public class PasspointProviderTest extends WifiBaseTest { // Setup test provider. PasspointConfiguration config = generateTestPasspointConfiguration( CredentialType.SIM, false); - when(mSimAccessor.getMatchingImsis(new IMSIParameter(TEST_IMSI, false))) - .thenReturn(Arrays.asList(new String[] {TEST_IMSI})); + when(mTelephonyUtil.getMatchingImsiCarrierId(TEST_IMSI)) + .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID)); mProvider = createProvider(config); // Setup ANQP elements. @@ -745,6 +747,9 @@ public class PasspointProviderTest extends WifiBaseTest { PasspointConfiguration config = generateTestPasspointConfiguration( CredentialType.SIM, false); mProvider = createProvider(config); + when(mTelephonyUtil.getMatchingImsiCarrierId( + eq(config.getCredential().getSimCredential().getImsi()))) + .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID)); // Setup Roaming Consortium ANQP element. Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); @@ -919,8 +924,8 @@ public class PasspointProviderTest extends WifiBaseTest { // Setup test provider. PasspointConfiguration config = generateTestPasspointConfiguration( CredentialType.SIM, false); - when(mSimAccessor.getMatchingImsis(new IMSIParameter(TEST_IMSI, false))) - .thenReturn(Arrays.asList(new String[] {TEST_IMSI})); + when(mTelephonyUtil.getMatchingImsiCarrierId(TEST_IMSI)) + .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID)); mProvider = createProvider(config); // Setup 3GPP Network ANQP element. @@ -949,8 +954,8 @@ public class PasspointProviderTest extends WifiBaseTest { // Setup test provider. PasspointConfiguration config = generateTestPasspointConfiguration( CredentialType.SIM, false); - when(mSimAccessor.getMatchingImsis(new IMSIParameter(TEST_IMSI, false))) - .thenReturn(Arrays.asList(new String[] {TEST_IMSI})); + when(mTelephonyUtil.getMatchingImsiCarrierId(TEST_IMSI)) + .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID)); mProvider = createProvider(config); // Setup 3GPP Network ANQP element. @@ -964,6 +969,64 @@ public class PasspointProviderTest extends WifiBaseTest { assertEquals(PasspointMatch.RoamingProvider, mProvider.match(anqpElementMap, mRoamingConsortium)); + assertEquals(VALID_CARRIER_ID, mProvider.getWifiConfig().carrierId); + } + + /** + * Verify that when the SIM card matched by carrier ID of profile is absent, it shouldn't + * be matched even the profile and ANQP elements are matched. + * + * @throws Exception + */ + @Test + public void matchNothingIfSimMatchedByCarrierIdIsAbsent() throws Exception { + // Setup test provider. + PasspointConfiguration config = generateTestPasspointConfiguration( + CredentialType.SIM, false); + config.setCarrierId(VALID_CARRIER_ID); + when(mTelephonyUtil.getMatchingImsi(eq(VALID_CARRIER_ID))) + .thenReturn(null); + mProvider = createProvider(config); + + // Setup 3GPP Network ANQP element. + Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); + anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork, + createThreeGPPNetworkElement(new String[] {"123456"})); + + // Setup NAI Realm ANQP element with same realm. + anqpElementMap.put(ANQPElementType.ANQPNAIRealm, + createNAIRealmElement(TEST_REALM, EAPConstants.EAP_AKA, null)); + + assertEquals(PasspointMatch.None, + mProvider.match(anqpElementMap, mRoamingConsortium)); + } + + /** + * Verify that when the SIM card matched by IMSI of profile is absent, it shouldn't be + * matched even the profile and ANQP elements are matched. + * + * @throws Exception + */ + @Test + public void matchNothingIfSimMatchedByImsiIsAbsent() throws Exception { + // Setup test provider. + PasspointConfiguration config = generateTestPasspointConfiguration( + CredentialType.SIM, false); + when(mTelephonyUtil.getMatchingImsiCarrierId(eq(TEST_IMSI))) + .thenReturn(null); + mProvider = createProvider(config); + + // Setup 3GPP Network ANQP element. + Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); + anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork, + createThreeGPPNetworkElement(new String[] {"123456"})); + + // Setup NAI Realm ANQP element with same realm. + anqpElementMap.put(ANQPElementType.ANQPNAIRealm, + createNAIRealmElement(TEST_REALM, EAPConstants.EAP_AKA, null)); + + assertEquals(PasspointMatch.None, + mProvider.match(anqpElementMap, mRoamingConsortium)); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java index b31bb057e..7e24c8572 100644 --- a/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java +++ b/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java @@ -24,6 +24,8 @@ import static org.mockito.Mockito.*; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiEnterpriseConfig; +import android.net.wifi.hotspot2.PasspointConfiguration; +import android.net.wifi.hotspot2.pps.Credential; import android.telephony.ImsiEncryptionInfo; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; @@ -67,8 +69,18 @@ public class TelephonyUtilTest extends WifiBaseTest { private static final int NON_DATA_SUBID = 2; private static final int INVALID_SUBID = -1; private static final int DATA_CARRIER_ID = 10; + private static final int PARENT_DATA_CARRIER_ID = 11; private static final int NON_DATA_CARRIER_ID = 20; + private static final int PARENT_NON_DATA_CARRIER_ID = 21; private static final int DEACTIVE_CARRIER_ID = 30; + private static final String MATCH_PREFIX_IMSI = "123456*"; + private static final String DATA_FULL_IMSI = "123456789123456"; + private static final String NON_DATA_FULL_IMSI = "123456987654321"; + private static final String NO_MATCH_FULL_IMSI = "654321123456789"; + private static final String NO_MATCH_PREFIX_IMSI = "654321*"; + private static final String DATA_OPERATOR_NUMERIC = "123456"; + private static final String NON_DATA_OPERATOR_NUMERIC = "123456"; + private static final String NO_MATCH_OPERATOR_NUMERIC = "654321"; private List<SubscriptionInfo> mSubInfoList; @@ -109,10 +121,21 @@ public class TelephonyUtilTest extends WifiBaseTest { doReturn(true).when( () -> SubscriptionManager.isValidSubscriptionId(NON_DATA_SUBID)); + when(mTelephonyManager.getSubscriberId(eq(DATA_SUBID))).thenReturn(DATA_FULL_IMSI); + when(mTelephonyManager.getSubscriberId(eq(NON_DATA_SUBID))).thenReturn(NON_DATA_FULL_IMSI); when(mDataSubscriptionInfo.getCarrierId()).thenReturn(DATA_CARRIER_ID); when(mDataSubscriptionInfo.getSubscriptionId()).thenReturn(DATA_SUBID); when(mNonDataSubscriptionInfo.getCarrierId()).thenReturn(NON_DATA_CARRIER_ID); when(mNonDataSubscriptionInfo.getSubscriptionId()).thenReturn(NON_DATA_SUBID); + when(mDataTelephonyManager.getSubscriberId()).thenReturn(DATA_FULL_IMSI); + when(mNonDataTelephonyManager.getSubscriberId()).thenReturn(NON_DATA_FULL_IMSI); + when(mDataTelephonyManager.getSimOperatorNumeric()).thenReturn(DATA_OPERATOR_NUMERIC); + when(mNonDataTelephonyManager.getSimOperatorNumeric()) + .thenReturn(NON_DATA_OPERATOR_NUMERIC); + when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); + when(mNonDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); + when(mSubscriptionManager.getActiveSubscriptionIdList()) + .thenReturn(new int[]{DATA_SUBID, NON_DATA_SUBID}); } @After @@ -689,6 +712,7 @@ public class TelephonyUtilTest extends WifiBaseTest { WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null); + when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[0]); assertEquals(INVALID_SUBID, mTelephonyUtil.getBestMatchSubscriptionId(config)); @@ -702,7 +726,7 @@ public class TelephonyUtilTest extends WifiBaseTest { * The matched Subscription ID should be that of data SIM when carrier ID is not specified. */ @Test - public void getBestMatchSubscriptionIdWithoutCarrierIdFieldForSimConfig() { + public void getBestMatchSubscriptionIdForEnterpriseWithoutCarrierIdFieldForSimConfig() { WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); @@ -714,7 +738,7 @@ public class TelephonyUtilTest extends WifiBaseTest { * SIM card and the carrier ID is not specified. */ @Test - public void getBestMatchSubscriptionIdWithoutCarrierIdFieldForNonSimConfig() { + public void getBestMatchSubscriptionIdForEnterpriseWithoutCarrierIdFieldForNonSimConfig() { WifiConfiguration config = new WifiConfiguration(); assertEquals(INVALID_SUBID, mTelephonyUtil.getBestMatchSubscriptionId(config)); @@ -725,7 +749,7 @@ public class TelephonyUtilTest extends WifiBaseTest { * should be returned. */ @Test - public void getBestMatchSubscriptionIdWithNonDataCarrierId() { + public void getBestMatchSubscriptionIdForEnterpriseWithNonDataCarrierId() { WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); config.carrierId = NON_DATA_CARRIER_ID; @@ -737,6 +761,33 @@ public class TelephonyUtilTest extends WifiBaseTest { } /** + * If the passpoint profile have valid carrier ID, the matching sub ID should be returned. + */ + @Test + public void getBestMatchSubscriptionIdForPasspointWithValidCarrierId() { + WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( + WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); + config.carrierId = DATA_CARRIER_ID; + WifiConfiguration spyConfig = spy(config); + doReturn(true).when(spyConfig).isPasspoint(); + + assertEquals(DATA_SUBID, mTelephonyUtil.getBestMatchSubscriptionId(spyConfig)); + } + + /** + * If there is no matching SIM card, the matching sub ID should be invalid. + */ + @Test + public void getBestMatchSubscriptionIdForPasspointInvalidCarrierId() { + WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( + WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); + WifiConfiguration spyConfig = spy(config); + doReturn(true).when(spyConfig).isPasspoint(); + + assertEquals(INVALID_SUBID, mTelephonyUtil.getBestMatchSubscriptionId(spyConfig)); + } + + /** * The matched Subscription ID should be invalid if the SIM card for the specified carrier ID * is absent. */ @@ -748,4 +799,256 @@ public class TelephonyUtilTest extends WifiBaseTest { assertEquals(INVALID_SUBID, mTelephonyUtil.getBestMatchSubscriptionId(config)); } + + /** + * Verify that the result is null if no active SIM is matched. + */ + @Test + public void getMatchingImsiCarrierIdWithDeactiveCarrierId() { + when(mSubscriptionManager.getActiveSubscriptionInfoList()) + .thenReturn(Collections.emptyList()); + + assertNull(mTelephonyUtil.getMatchingImsi(DEACTIVE_CARRIER_ID)); + } + + /** + * Verify that if there is SIM card whose carrier ID is the same as the input, the correct IMSI + * and carrier ID would be returned. + */ + @Test + public void getMatchingImsiCarrierIdWithValidCarrierId() { + assertEquals(DATA_FULL_IMSI, + mTelephonyUtil.getMatchingImsi(DATA_CARRIER_ID)); + } + + /** + * Verify that if there is no SIM, it should match nothing. + */ + @Test + public void getMatchingImsiCarrierIdWithEmptyActiveSubscriptionInfoList() { + when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null); + + assertNull(mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); + + when(mSubscriptionManager.getActiveSubscriptionInfoList()) + .thenReturn(Collections.emptyList()); + + assertNull(mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); + } + + /** + * Verify that if there is no matching SIM, it should match nothing. + */ + @Test + public void getMatchingImsiCarrierIdWithNoMatchImsi() { + // data SIM is MNO. + when(mDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(DATA_CARRIER_ID); + when(mDataTelephonyManager.getSimCarrierId()).thenReturn(DATA_CARRIER_ID); + // non data SIM is MNO. + when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(NON_DATA_CARRIER_ID); + when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); + + assertNull(mTelephonyUtil.getMatchingImsiCarrierId(NO_MATCH_PREFIX_IMSI)); + } + + /** + * Verify that if the matched SIM is the default data SIM and a MNO SIM, the information of it + * should be returned. + */ + @Test + public void getMatchingImsiCarrierIdForDataAndMnoSimMatch() { + // data SIM is MNO. + when(mDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(DATA_CARRIER_ID); + when(mDataTelephonyManager.getSimCarrierId()).thenReturn(DATA_CARRIER_ID); + // non data SIM is MNO. + when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(NON_DATA_CARRIER_ID); + when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); + + Pair<String, Integer> ic = mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI); + + assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID), ic); + + // non data SIM is MVNO + when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()) + .thenReturn(PARENT_NON_DATA_CARRIER_ID); + when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); + + assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID), + mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); + + // non data SIM doesn't match. + when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(NON_DATA_CARRIER_ID); + when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); + when(mNonDataTelephonyManager.getSubscriberId()).thenReturn(NO_MATCH_FULL_IMSI); + when(mNonDataTelephonyManager.getSimOperatorNumeric()) + .thenReturn(NO_MATCH_OPERATOR_NUMERIC); + + assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID), + mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); + } + + /** + * Verify that if the matched SIM is the default data SIM and a MVNO SIM, and no MNO SIM was + * matched, the information of it should be returned. + */ + @Test + public void getMatchingImsiCarrierIdForDataAndMvnoSimMatch() { + // data SIM is MVNO. + when(mDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(PARENT_DATA_CARRIER_ID); + when(mDataTelephonyManager.getSimCarrierId()).thenReturn(DATA_CARRIER_ID); + // non data SIM is MVNO. + when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()) + .thenReturn(PARENT_NON_DATA_CARRIER_ID); + when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); + + Pair<String, Integer> ic = mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI); + + assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID), ic); + + // non data SIM doesn't match. + when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(NON_DATA_CARRIER_ID); + when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); + when(mNonDataTelephonyManager.getSubscriberId()).thenReturn(NO_MATCH_FULL_IMSI); + when(mNonDataTelephonyManager.getSimOperatorNumeric()) + .thenReturn(NO_MATCH_OPERATOR_NUMERIC); + + assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID), + mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); + } + + /** + * Verify that if the matched SIM is a MNO SIM, even the default data SIM is matched as a MVNO + * SIM, the information of MNO SIM still should be returned. + */ + @Test + public void getMatchingImsiCarrierIdForNonDataAndMnoSimMatch() { + // data SIM is MVNO. + when(mDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(PARENT_DATA_CARRIER_ID); + when(mDataTelephonyManager.getSimCarrierId()).thenReturn(DATA_CARRIER_ID); + // non data SIM is MNO. + when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(NON_DATA_CARRIER_ID); + when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); + + + Pair<String, Integer> ic = mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI); + + assertEquals(new Pair<>(NON_DATA_FULL_IMSI, NON_DATA_CARRIER_ID), ic); + + // data SIM doesn't match + when(mDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(DATA_CARRIER_ID); + when(mDataTelephonyManager.getSimCarrierId()).thenReturn(DATA_CARRIER_ID); + when(mDataTelephonyManager.getSubscriberId()).thenReturn(NO_MATCH_FULL_IMSI); + when(mDataTelephonyManager.getSimOperatorNumeric()).thenReturn(NO_MATCH_OPERATOR_NUMERIC); + + assertEquals(new Pair<>(NON_DATA_FULL_IMSI, NON_DATA_CARRIER_ID), + mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); + } + + /** + * Verify that if only a MVNO SIM is matched, the information of it should be returned. + */ + @Test + public void getMatchingImsiCarrierIdForMvnoSimMatch() { + // data SIM is MNO, but IMSI doesn't match. + when(mDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(DATA_CARRIER_ID); + when(mDataTelephonyManager.getSimCarrierId()).thenReturn(DATA_CARRIER_ID); + when(mDataTelephonyManager.getSubscriberId()).thenReturn(NO_MATCH_FULL_IMSI); + when(mDataTelephonyManager.getSimOperatorNumeric()).thenReturn(NO_MATCH_OPERATOR_NUMERIC); + // non data SIM is MVNO. + when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()) + .thenReturn(PARENT_NON_DATA_CARRIER_ID); + when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); + + assertEquals(new Pair<>(NON_DATA_FULL_IMSI, NON_DATA_CARRIER_ID), + mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); + } + + /** + * Verify that if there is no any SIM card, the carrier ID should be updated. + */ + @Test + public void tryUpdateCarrierIdForPasspointWithEmptyActiveSubscriptionList() { + PasspointConfiguration config = mock(PasspointConfiguration.class); + when(config.getCarrierId()).thenReturn(DATA_CARRIER_ID); + when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null); + + assertFalse(mTelephonyUtil.tryUpdateCarrierIdForPasspoint(config)); + + when(mSubscriptionManager.getActiveSubscriptionInfoList()) + .thenReturn(Collections.emptyList()); + + assertFalse(mTelephonyUtil.tryUpdateCarrierIdForPasspoint(config)); + } + + /** + * Verify that if the carrier ID has been assigned, it shouldn't be updated. + */ + @Test + public void tryUpdateCarrierIdForPasspointWithValidCarrieId() { + PasspointConfiguration config = mock(PasspointConfiguration.class); + when(config.getCarrierId()).thenReturn(DATA_CARRIER_ID); + + assertFalse(mTelephonyUtil.tryUpdateCarrierIdForPasspoint(config)); + } + + /** + * Verify that if the passpoint profile doesn't have SIM credential, it shouldn't be updated. + */ + @Test + public void tryUpdateCarrierIdForPasspointWithNonSimCredential() { + Credential credential = mock(Credential.class); + PasspointConfiguration spyConfig = spy(new PasspointConfiguration()); + doReturn(credential).when(spyConfig).getCredential(); + when(credential.getSimCredential()).thenReturn(null); + + assertFalse(mTelephonyUtil.tryUpdateCarrierIdForPasspoint(spyConfig)); + } + + /** + * Verify that if the passpoint profile only have IMSI prefix(mccmnc*) parameter, + * it shouldn't be updated. + */ + @Test + public void tryUpdateCarrierIdForPasspointWithPrefixImsi() { + Credential credential = mock(Credential.class); + PasspointConfiguration spyConfig = spy(new PasspointConfiguration()); + doReturn(credential).when(spyConfig).getCredential(); + Credential.SimCredential simCredential = mock(Credential.SimCredential.class); + when(credential.getSimCredential()).thenReturn(simCredential); + when(simCredential.getImsi()).thenReturn(MATCH_PREFIX_IMSI); + + assertFalse(mTelephonyUtil.tryUpdateCarrierIdForPasspoint(spyConfig)); + } + + /** + * Verify that if the passpoint profile has the full IMSI and wasn't assigned valid + * carrier ID, it should be updated. + */ + @Test + public void tryUpdateCarrierIdForPasspointWithFullImsiAndActiveSim() { + Credential credential = mock(Credential.class); + PasspointConfiguration spyConfig = spy(new PasspointConfiguration()); + doReturn(credential).when(spyConfig).getCredential(); + Credential.SimCredential simCredential = mock(Credential.SimCredential.class); + when(credential.getSimCredential()).thenReturn(simCredential); + when(simCredential.getImsi()).thenReturn(DATA_FULL_IMSI); + + assertTrue(mTelephonyUtil.tryUpdateCarrierIdForPasspoint(spyConfig)); + assertEquals(DATA_CARRIER_ID, spyConfig.getCarrierId()); + } + + /** + * Verify that if there is no SIM card matching the given IMSI, it shouldn't be updated. + */ + @Test + public void tryUpdateCarrierIdForPasspointWithFullImsiAndInactiveSim() { + Credential credential = mock(Credential.class); + PasspointConfiguration spyConfig = spy(new PasspointConfiguration()); + doReturn(credential).when(spyConfig).getCredential(); + Credential.SimCredential simCredential = mock(Credential.SimCredential.class); + when(credential.getSimCredential()).thenReturn(simCredential); + when(simCredential.getImsi()).thenReturn(NO_MATCH_PREFIX_IMSI); + + assertFalse(mTelephonyUtil.tryUpdateCarrierIdForPasspoint(spyConfig)); + } } |