187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu/*
287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu * Copyright (C) 2016 The Android Open Source Project
387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu *
487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu * Licensed under the Apache License, Version 2.0 (the "License");
587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu * you may not use this file except in compliance with the License.
687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu * You may obtain a copy of the License at
787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu *
887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu *      http://www.apache.org/licenses/LICENSE-2.0
987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu *
1087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu * Unless required by applicable law or agreed to in writing, software
1187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu * distributed under the License is distributed on an "AS IS" BASIS,
1287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu * See the License for the specific language governing permissions and
1487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu * limitations under the License.
1587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu */
1687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
1787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiupackage com.android.server.wifi.hotspot2;
1887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
1987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiuimport com.android.server.wifi.IMSIParameter;
2087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiuimport com.android.server.wifi.hotspot2.anqp.CellularNetwork;
2187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiuimport com.android.server.wifi.hotspot2.anqp.DomainNameElement;
2287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiuimport com.android.server.wifi.hotspot2.anqp.NAIRealmData;
2387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiuimport com.android.server.wifi.hotspot2.anqp.NAIRealmElement;
2487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiuimport com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement;
2587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiuimport com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement;
2687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiuimport com.android.server.wifi.hotspot2.anqp.eap.AuthParam;
2787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiuimport com.android.server.wifi.hotspot2.anqp.eap.EAPMethod;
2887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
2987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiuimport java.util.List;
3087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiuimport java.util.Map;
3187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiuimport java.util.Set;
3287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
3387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu/**
3487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu * Utility class for providing matching functions against ANQP elements.
3587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu */
3687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiupublic class ANQPMatcher {
3787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    /**
3887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * Match the domain names in the ANQP element against the provider's FQDN and SIM credential.
3987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * The Domain Name ANQP element might contain domains for 3GPP network (e.g.
4087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * wlan.mnc*.mcc*.3gppnetwork.org), so we should match that against the provider's SIM
4187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * credential if one is provided.
4287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     *
4387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param element The Domain Name ANQP element
4487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param fqdn The FQDN to compare against
4587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param imsiParam The IMSI parameter of the provider
4687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param simImsiList The list of IMSI from the installed SIM cards that matched provider's
4787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     *                    IMSI parameter
4887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @return true if a match is found
4987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     */
5087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    public static boolean matchDomainName(DomainNameElement element, String fqdn,
5187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            IMSIParameter imsiParam, List<String> simImsiList) {
5287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        if (element == null) {
5387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            return false;
5487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
5587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
5687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        for (String domain : element.getDomains()) {
5787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            if (DomainMatcher.arg2SubdomainOfArg1(fqdn, domain)) {
5887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu                return true;
5987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            }
6087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
6187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            // Try to retrieve the MCC-MNC string from the domain (for 3GPP network domain) and
6287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            // match against the provider's SIM credential.
6387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            if (matchMccMnc(Utils.getMccMnc(Utils.splitDomain(domain)), imsiParam, simImsiList)) {
6487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu                return true;
6587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            }
6687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
6787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        return false;
6887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    }
6987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
7087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    /**
7187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * Match the roaming consortium OIs in the ANQP element against the roaming consortium OIs
7287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * of a provider.
7387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     *
7487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param element The Roaming Consortium ANQP element
7587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param providerOIs The roaming consortium OIs of the provider
7687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @return true if a match is found
7787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     */
7887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    public static boolean matchRoamingConsortium(RoamingConsortiumElement element,
7987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            long[] providerOIs) {
8087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        if (element == null) {
8187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            return false;
8287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
8387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        if (providerOIs == null) {
8487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            return false;
8587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
8687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        List<Long> rcOIs = element.getOIs();
8787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        for (long oi : providerOIs) {
8887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            if (rcOIs.contains(oi)) {
8987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu                return true;
9087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            }
9187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
9287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        return false;
9387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    }
9487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
9587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    /**
9687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * Match the NAI realm in the ANQP element against the realm and authentication method of
9787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * a provider.
9887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     *
9987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param element The NAI Realm ANQP element
10087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param realm The realm of the provider's credential
10187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param eapMethodID The EAP Method ID of the provider's credential
10287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param authParam The authentication parameter of the provider's credential
10387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @return an integer indicating the match status
10487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     */
10587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    public static int matchNAIRealm(NAIRealmElement element, String realm, int eapMethodID,
10687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            AuthParam authParam) {
10787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        if (element == null || element.getRealmDataList().isEmpty()) {
10887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            return AuthMatch.INDETERMINATE;
10987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
11087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
11187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        int bestMatch = AuthMatch.NONE;
11287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        for (NAIRealmData realmData : element.getRealmDataList()) {
11387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            int match = matchNAIRealmData(realmData, realm, eapMethodID, authParam);
11487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            if (match > bestMatch) {
11587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu                bestMatch = match;
11687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu                if (bestMatch == AuthMatch.EXACT) {
11787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu                    break;
11887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu                }
11987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            }
12087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
12187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        return bestMatch;
12287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    }
12387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
12487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    /**
12587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * Match the 3GPP Network in the ANQP element against the SIM credential of a provider.
12687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     *
12787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param element 3GPP Network ANQP element
12887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param imsiParam The IMSI parameter of the provider's SIM credential
12987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param simImsiList The list of IMSI from the installed SIM cards that matched provider's
13087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     *                    IMSI parameter
13187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @return true if a matched is found
13287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     */
13387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    public static  boolean matchThreeGPPNetwork(ThreeGPPNetworkElement element,
13487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            IMSIParameter imsiParam, List<String> simImsiList) {
13587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        if (element == null) {
13687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            return false;
13787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
13887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        for (CellularNetwork network : element.getNetworks()) {
13987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            if (matchCellularNetwork(network, imsiParam, simImsiList)) {
14087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu                return true;
14187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            }
14287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
14387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        return false;
14487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    }
14587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
14687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    /**
14787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * Match the given NAI Realm data against the realm and authentication method of a provider.
14887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     *
14987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param realmData The NAI Realm data
15087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param realm The realm of the provider's credential
15187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param eapMethodID The EAP Method ID of the provider's credential
15287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param authParam The authentication parameter of the provider's credential
15387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @return an integer indicating the match status
15487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     */
15587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    private static int matchNAIRealmData(NAIRealmData realmData, String realm, int eapMethodID,
15687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            AuthParam authParam) {
15787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        // Check for realm domain name match.
15887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        int realmMatch = AuthMatch.NONE;
15987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        for (String realmStr : realmData.getRealms()) {
16087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            if (DomainMatcher.arg2SubdomainOfArg1(realm, realmStr)) {
16187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu                realmMatch = AuthMatch.REALM;
16287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu                break;
16387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            }
16487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
16587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
16687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        if (realmMatch == AuthMatch.NONE || realmData.getEAPMethods().isEmpty()) {
16787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            return realmMatch;
16887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
16987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
17087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        // Check for EAP method match.
17187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        int eapMethodMatch = AuthMatch.NONE;
17287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        for (EAPMethod eapMethod : realmData.getEAPMethods()) {
17387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            eapMethodMatch = matchEAPMethod(eapMethod, eapMethodID, authParam);
17487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            if (eapMethodMatch != AuthMatch.NONE) {
17587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu                break;
17687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            }
17787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
17887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
17987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        if (eapMethodMatch == AuthMatch.NONE) {
18087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            return AuthMatch.NONE;
18187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
18287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        return realmMatch | eapMethodMatch;
18387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    }
18487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
18587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    /**
18687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * Match the given EAPMethod against the authentication method of a provider.
18787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     *
18887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param method The EAP Method
18987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param eapMethodID The EAP Method ID of the provider's credential
19087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param authParam The authentication parameter of the provider's credential
19187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @return an integer indicating the match status
19287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     */
19387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    private static int matchEAPMethod(EAPMethod method, int eapMethodID, AuthParam authParam) {
19487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        if (method.getEAPMethodID() != eapMethodID) {
19587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            return AuthMatch.NONE;
19687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
19787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        // Check for authentication parameter match.
19887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        if (authParam != null) {
19987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            Map<Integer, Set<AuthParam>> authParams = method.getAuthParams();
20087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            Set<AuthParam> paramSet = authParams.get(authParam.getAuthTypeID());
20187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            if (paramSet == null || !paramSet.contains(authParam)) {
20287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu                return AuthMatch.NONE;
20387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            }
20487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            return AuthMatch.METHOD_PARAM;
20587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
20687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        return AuthMatch.METHOD;
20787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    }
20887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
20987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    /**
21087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * Match a cellular network information in the 3GPP Network ANQP element against the SIM
21187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * credential of a provider.
21287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     *
21387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param network The cellular network that contained list of PLMNs
21487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param imsiParam IMSI parameter of the provider
21587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param simImsiList The list of IMSI from the installed SIM cards that matched provider's
21687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     *                    IMSI parameter
21787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @return true if a match is found
21887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     */
21987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    private static boolean matchCellularNetwork(CellularNetwork network, IMSIParameter imsiParam,
22087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            List<String> simImsiList) {
22187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        for (String plmn : network.getPlmns()) {
22287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            if (matchMccMnc(plmn, imsiParam, simImsiList)) {
22387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu                return true;
22487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            }
22587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
22687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        return false;
22787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    }
22887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu
22987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    /**
23087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * Match a MCC-MNC against the SIM credential of a provider.
23187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     *
23287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param mccMnc The string containing MCC-MNC
23387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param imsiParam The IMSI parameter of the provider
23487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @param simImsiList The list of IMSI from the installed SIM cards that matched provider's
23587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     *                    IMSI parameter
23687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     * @return true if a match is found
23787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu     */
23887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    private static boolean matchMccMnc(String mccMnc, IMSIParameter imsiParam,
23987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            List<String> simImsiList) {
24087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        if (imsiParam == null || simImsiList == null) {
24187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            return false;
24287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
24387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        // Match against the IMSI parameter in the provider.
24487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        if (!imsiParam.matchesMccMnc(mccMnc)) {
24587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            return false;
24687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
24787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        // Additional check for verifying the match with IMSIs from the SIM cards, since the IMSI
24887c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        // parameter might not contain the full 6-digit MCC MNC (e.g. IMSI parameter is an IMSI
24987c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        // prefix that contained less than 6-digit of numbers "12345*").
25087c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        for (String imsi : simImsiList) {
25187c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            if (imsi.startsWith(mccMnc)) {
25287c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu                return true;
25387c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu            }
25487c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        }
25587c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu        return false;
25687c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu    }
25787c6f1b149804685e46c18d2ad11262f611c9255Peter Qiu}
258