/*
 * Copyright 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.internal.telephony;

import static android.provider.Telephony.CarrierId;

import android.annotation.NonNull;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.provider.Telephony;
import android.service.carrier.CarrierIdentifier;
import android.telephony.PhoneStateListener;
import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.telephony.uicc.IccRecords;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.util.IndentingPrintWriter;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * CarrierResolver identifies the subscription carrier and returns a canonical carrier Id
 * and a user friendly carrier name. CarrierResolver reads subscription info and check against
 * all carrier matching rules stored in CarrierIdProvider. It is msim aware, each phone has a
 * dedicated CarrierResolver.
 */
public class CarrierResolver extends Handler {
    private static final String LOG_TAG = CarrierResolver.class.getSimpleName();
    private static final boolean DBG = true;
    private static final boolean VDBG = Rlog.isLoggable(LOG_TAG, Log.VERBOSE);

    // events to trigger carrier identification
    private static final int SIM_LOAD_EVENT             = 1;
    private static final int ICC_CHANGED_EVENT          = 2;
    private static final int PREFER_APN_UPDATE_EVENT    = 3;
    private static final int CARRIER_ID_DB_UPDATE_EVENT = 4;

    private static final Uri CONTENT_URL_PREFER_APN = Uri.withAppendedPath(
            Telephony.Carriers.CONTENT_URI, "preferapn");

    // cached matching rules based mccmnc to speed up resolution
    private List<CarrierMatchingRule> mCarrierMatchingRulesOnMccMnc = new ArrayList<>();
    // cached carrier Id
    private int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
    // cached specific carrier Id
    private int mSpecificCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
    // cached MNO carrier Id. mno carrier shares the same mccmnc as cid and can be solely
    // identified by mccmnc only. If there is no such mno carrier, mno carrier id equals to
    // the cid.
    private int mMnoCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
    // cached carrier name
    private String mCarrierName;
    private String mSpecificCarrierName;
    // cached preferapn name
    private String mPreferApn;
    // override for testing purpose
    private String mTestOverrideApn;
    private String mTestOverrideCarrierPriviledgeRule;
    // cached service provider name. telephonyManager API returns empty string as default value.
    // some carriers need to target devices with Empty SPN. In that case, carrier matching rule
    // should specify "" spn explicitly.
    private String mSpn = "";

    private Context mContext;
    private Phone mPhone;
    private IccRecords mIccRecords;
    private final LocalLog mCarrierIdLocalLog = new LocalLog(20);
    private final TelephonyManager mTelephonyMgr;

    private final ContentObserver mContentObserver = new ContentObserver(this) {
        @Override
        public void onChange(boolean selfChange, Uri uri) {
            if (CONTENT_URL_PREFER_APN.equals(uri.getLastPathSegment())) {
                logd("onChange URI: " + uri);
                sendEmptyMessage(PREFER_APN_UPDATE_EVENT);
            } else if (CarrierId.All.CONTENT_URI.equals(uri)) {
                logd("onChange URI: " + uri);
                sendEmptyMessage(CARRIER_ID_DB_UPDATE_EVENT);
            }
        }
    };

    public CarrierResolver(Phone phone) {
        logd("Creating CarrierResolver[" + phone.getPhoneId() + "]");
        mContext = phone.getContext();
        mPhone = phone;
        mTelephonyMgr = TelephonyManager.from(mContext);

        // register events
        mContext.getContentResolver().registerContentObserver(CONTENT_URL_PREFER_APN, false,
                mContentObserver);
        mContext.getContentResolver().registerContentObserver(
                CarrierId.All.CONTENT_URI, false, mContentObserver);
        UiccController.getInstance().registerForIccChanged(this, ICC_CHANGED_EVENT, null);
    }

    /**
     * This is triggered from SubscriptionInfoUpdater after sim state change.
     * The sequence of sim loading would be
     *  1. ACTION_SUBINFO_CONTENT_CHANGE
     *  2. ACTION_SIM_STATE_CHANGED/ACTION_SIM_CARD_STATE_CHANGED
     *  /ACTION_SIM_APPLICATION_STATE_CHANGED
     *  3. ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED
     *
     *  For SIM refresh either reset or init refresh type, SubscriptionInfoUpdater will re-trigger
     *  carrier identification with sim loaded state. Framework today silently handle single file
     *  refresh type.
     *  TODO: check fileId from single file refresh, if the refresh file is IMSI, gid1 or other
     *  records which might change carrier id, framework should trigger sim loaded state just like
     *  other refresh events: INIT or RESET and which will ultimately trigger carrier
     *  re-identification.
     */
    public void resolveSubscriptionCarrierId(String simState) {
        logd("[resolveSubscriptionCarrierId] simState: " + simState);
        switch (simState) {
            case IccCardConstants.INTENT_VALUE_ICC_ABSENT:
            case IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR:
                // only clear carrier id on absent to avoid transition to unknown carrier id during
                // intermediate states of sim refresh
                handleSimAbsent();
                break;
            case IccCardConstants.INTENT_VALUE_ICC_LOADED:
                handleSimLoaded();
                break;
        }
    }

    private void handleSimLoaded() {
        if (mIccRecords != null) {
            /**
             * returns empty string to be consistent with
             * {@link TelephonyManager#getSimOperatorName()}
             */
            mSpn = (mIccRecords.getServiceProviderName() == null) ? ""
                    : mIccRecords.getServiceProviderName();
        } else {
            loge("mIccRecords is null on SIM_LOAD_EVENT, could not get SPN");
        }
        mPreferApn = getPreferApn();
        loadCarrierMatchingRulesOnMccMnc();
    }

    private void handleSimAbsent() {
        mCarrierMatchingRulesOnMccMnc.clear();
        mSpn = null;
        mPreferApn = null;
        updateCarrierIdAndName(TelephonyManager.UNKNOWN_CARRIER_ID, null,
                TelephonyManager.UNKNOWN_CARRIER_ID, null,
                TelephonyManager.UNKNOWN_CARRIER_ID);
    }

    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
        @Override
        public void onCallStateChanged(int state, String ignored) {
        }
    };

    /**
     * Entry point for the carrier identification.
     *
     *    1. SIM_LOAD_EVENT
     *        This indicates that all SIM records has been loaded and its first entry point for the
     *        carrier identification. Note, there are other attributes could be changed on the fly
     *        like APN. We cached all carrier matching rules based on MCCMNC to speed
     *        up carrier resolution on following trigger events.
     *
     *    2. PREFER_APN_UPDATE_EVENT
     *        This indicates prefer apn has been changed. It could be triggered when user modified
     *        APN settings or when default data connection first establishes on the current carrier.
     *        We follow up on this by querying prefer apn sqlite and re-issue carrier identification
     *        with the updated prefer apn name.
     *
     *    3. CARRIER_ID_DB_UPDATE_EVENT
     *        This indicates that carrierIdentification database which stores all matching rules
     *        has been updated. It could be triggered from OTA or assets update.
     */
    @Override
    public void handleMessage(Message msg) {
        if (DBG) logd("handleMessage: " + msg.what);
        switch (msg.what) {
            case SIM_LOAD_EVENT:
                handleSimLoaded();
                break;
            case CARRIER_ID_DB_UPDATE_EVENT:
                loadCarrierMatchingRulesOnMccMnc();
                break;
            case PREFER_APN_UPDATE_EVENT:
                String preferApn = getPreferApn();
                if (!equals(mPreferApn, preferApn, true)) {
                    logd("[updatePreferApn] from:" + mPreferApn + " to:" + preferApn);
                    mPreferApn = preferApn;
                    matchSubscriptionCarrier();
                }
                break;
            case ICC_CHANGED_EVENT:
                // all records used for carrier identification are from SimRecord.
                final IccRecords newIccRecords = UiccController.getInstance().getIccRecords(
                        mPhone.getPhoneId(), UiccController.APP_FAM_3GPP);
                if (mIccRecords != newIccRecords) {
                    if (mIccRecords != null) {
                        logd("Removing stale icc objects.");
                        mIccRecords.unregisterForRecordsOverride(this);
                        mIccRecords = null;
                    }
                    if (newIccRecords != null) {
                        logd("new Icc object");
                        newIccRecords.registerForRecordsOverride(this, SIM_LOAD_EVENT, null);
                        mIccRecords = newIccRecords;
                    }
                }
                break;
            default:
                loge("invalid msg: " + msg.what);
                break;
        }
    }

    private void loadCarrierMatchingRulesOnMccMnc() {
        try {
            String mccmnc = mTelephonyMgr.getSimOperatorNumericForPhone(mPhone.getPhoneId());
            Cursor cursor = mContext.getContentResolver().query(
                    CarrierId.All.CONTENT_URI,
                    /* projection */ null,
                    /* selection */ CarrierId.All.MCCMNC + "=?",
                    /* selectionArgs */ new String[]{mccmnc}, null);
            try {
                if (cursor != null) {
                    if (VDBG) {
                        logd("[loadCarrierMatchingRules]- " + cursor.getCount()
                                + " Records(s) in DB" + " mccmnc: " + mccmnc);
                    }
                    mCarrierMatchingRulesOnMccMnc.clear();
                    while (cursor.moveToNext()) {
                        mCarrierMatchingRulesOnMccMnc.add(makeCarrierMatchingRule(cursor));
                    }
                    matchSubscriptionCarrier();
                }
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        } catch (Exception ex) {
            loge("[loadCarrierMatchingRules]- ex: " + ex);
        }
    }

    private String getCarrierNameFromId(int cid) {
        try {
            Cursor cursor = mContext.getContentResolver().query(
                    CarrierId.All.CONTENT_URI,
                    /* projection */ null,
                    /* selection */ CarrierId.CARRIER_ID + "=?",
                    /* selectionArgs */ new String[]{cid + ""}, null);
            try {
                if (cursor != null) {
                    if (VDBG) {
                        logd("[getCarrierNameFromId]- " + cursor.getCount()
                                + " Records(s) in DB" + " cid: " + cid);
                    }
                    while (cursor.moveToNext()) {
                        return cursor.getString(cursor.getColumnIndex(CarrierId.CARRIER_NAME));
                    }
                }
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        } catch (Exception ex) {
            loge("[getCarrierNameFromId]- ex: " + ex);
        }
        return null;
    }

    private static List<CarrierMatchingRule> getCarrierMatchingRulesFromMccMnc(
            @NonNull Context context, String mccmnc) {
        List<CarrierMatchingRule> rules = new ArrayList<>();
        try {
            Cursor cursor = context.getContentResolver().query(
                    CarrierId.All.CONTENT_URI,
                    /* projection */ null,
                    /* selection */ CarrierId.All.MCCMNC + "=?",
                    /* selectionArgs */ new String[]{mccmnc}, null);
            try {
                if (cursor != null) {
                    if (VDBG) {
                        logd("[loadCarrierMatchingRules]- " + cursor.getCount()
                                + " Records(s) in DB" + " mccmnc: " + mccmnc);
                    }
                    rules.clear();
                    while (cursor.moveToNext()) {
                        rules.add(makeCarrierMatchingRule(cursor));
                    }
                }
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        } catch (Exception ex) {
            loge("[loadCarrierMatchingRules]- ex: " + ex);
        }
        return rules;
    }

    private String getPreferApn() {
        // return test overrides if present
        if (!TextUtils.isEmpty(mTestOverrideApn)) {
            logd("[getPreferApn]- " + mTestOverrideApn + " test override");
            return mTestOverrideApn;
        }
        Cursor cursor = mContext.getContentResolver().query(
                Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "preferapn/subId/"
                + mPhone.getSubId()), /* projection */ new String[]{Telephony.Carriers.APN},
                /* selection */ null, /* selectionArgs */ null, /* sortOrder */ null);
        try {
            if (cursor != null) {
                if (VDBG) {
                    logd("[getPreferApn]- " + cursor.getCount() + " Records(s) in DB");
                }
                while (cursor.moveToNext()) {
                    String apn = cursor.getString(cursor.getColumnIndexOrThrow(
                            Telephony.Carriers.APN));
                    logd("[getPreferApn]- " + apn);
                    return apn;
                }
            }
        } catch (Exception ex) {
            loge("[getPreferApn]- exception: " + ex);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return null;
    }

    private boolean isPreferApnUserEdited(@NonNull String preferApn) {
        try (Cursor cursor = mContext.getContentResolver().query(
                Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI,
                        "preferapn/subId/" + mPhone.getSubId()),
                /* projection */ new String[]{Telephony.Carriers.EDITED_STATUS},
                /* selection */ Telephony.Carriers.APN + "=?",
                /* selectionArgs */ new String[]{preferApn}, /* sortOrder */ null) ) {
            if (cursor != null && cursor.moveToFirst()) {
                return cursor.getInt(cursor.getColumnIndexOrThrow(
                        Telephony.Carriers.EDITED_STATUS)) == Telephony.Carriers.USER_EDITED;
            }
        } catch (Exception ex) {
            loge("[isPreferApnUserEdited]- exception: " + ex);
        }
        return false;
    }

    public void setTestOverrideApn(String apn) {
        logd("[setTestOverrideApn]: " + apn);
        mTestOverrideApn = apn;
    }

    public void setTestOverrideCarrierPriviledgeRule(String rule) {
        logd("[setTestOverrideCarrierPriviledgeRule]: " + rule);
        mTestOverrideCarrierPriviledgeRule = rule;
    }

    private void updateCarrierIdAndName(int cid, String name,
                                        int specificCarrierId, String specificCarrierName,
                                        int mnoCid) {
        boolean update = false;
        if (specificCarrierId != mSpecificCarrierId) {
            logd("[updateSpecificCarrierId] from:" + mSpecificCarrierId + " to:"
                    + specificCarrierId);
            mSpecificCarrierId = specificCarrierId;
            update = true;
        }
        if (specificCarrierName != mSpecificCarrierName) {
            logd("[updateSpecificCarrierName] from:" + mSpecificCarrierName + " to:"
                    + specificCarrierName);
            mSpecificCarrierName = specificCarrierName;
            update = true;
        }
        if (update) {
            mCarrierIdLocalLog.log("[updateSpecificCarrierIdAndName] cid:"
                    + mSpecificCarrierId + " name:" + mSpecificCarrierName);
            final Intent intent = new Intent(TelephonyManager
                    .ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED);
            intent.putExtra(TelephonyManager.EXTRA_SPECIFIC_CARRIER_ID, mSpecificCarrierId);
            intent.putExtra(TelephonyManager.EXTRA_SPECIFIC_CARRIER_NAME, mSpecificCarrierName);
            intent.putExtra(TelephonyManager.EXTRA_SUBSCRIPTION_ID, mPhone.getSubId());
            mContext.sendBroadcast(intent);

            // notify content observers for specific carrier id change event.
            ContentValues cv = new ContentValues();
            cv.put(CarrierId.SPECIFIC_CARRIER_ID, mSpecificCarrierId);
            cv.put(CarrierId.SPECIFIC_CARRIER_ID_NAME, mSpecificCarrierName);
            mContext.getContentResolver().update(
                    Telephony.CarrierId.getSpecificCarrierIdUriForSubscriptionId(mPhone.getSubId()),
                    cv, null, null);
        }

        update = false;
        if (!equals(name, mCarrierName, true)) {
            logd("[updateCarrierName] from:" + mCarrierName + " to:" + name);
            mCarrierName = name;
            update = true;
        }
        if (cid != mCarrierId) {
            logd("[updateCarrierId] from:" + mCarrierId + " to:" + cid);
            mCarrierId = cid;
            update = true;
        }
        if (mnoCid != mMnoCarrierId) {
            logd("[updateMnoCarrierId] from:" + mMnoCarrierId + " to:" + mnoCid);
            mMnoCarrierId = mnoCid;
            update = true;
        }
        if (update) {
            mCarrierIdLocalLog.log("[updateCarrierIdAndName] cid:" + mCarrierId + " name:"
                    + mCarrierName + " mnoCid:" + mMnoCarrierId);
            final Intent intent = new Intent(TelephonyManager
                    .ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED);
            intent.putExtra(TelephonyManager.EXTRA_CARRIER_ID, mCarrierId);
            intent.putExtra(TelephonyManager.EXTRA_CARRIER_NAME, mCarrierName);
            intent.putExtra(TelephonyManager.EXTRA_SUBSCRIPTION_ID, mPhone.getSubId());
            mContext.sendBroadcast(intent);

            // notify content observers for carrier id change event
            ContentValues cv = new ContentValues();
            cv.put(CarrierId.CARRIER_ID, mCarrierId);
            cv.put(CarrierId.CARRIER_NAME, mCarrierName);
            mContext.getContentResolver().update(
                    Telephony.CarrierId.getUriForSubscriptionId(mPhone.getSubId()), cv, null, null);
        }
        // during esim profile switch, there is no sim absent thus carrier id will persist and
        // might not trigger an update if switch profiles for the same carrier. thus always update
        // subscriptioninfo db to make sure we have correct carrier id set.
        if (SubscriptionManager.isValidSubscriptionId(mPhone.getSubId())) {
            // only persist carrier id to simInfo db when subId is valid.
            SubscriptionController.getInstance().setCarrierId(mCarrierId, mPhone.getSubId());
        }
    }

    private static CarrierMatchingRule makeCarrierMatchingRule(Cursor cursor) {
        String certs = cursor.getString(
                cursor.getColumnIndexOrThrow(CarrierId.All.PRIVILEGE_ACCESS_RULE));
        return new CarrierMatchingRule(
                cursor.getString(cursor.getColumnIndexOrThrow(CarrierId.All.MCCMNC)),
                cursor.getString(cursor.getColumnIndexOrThrow(
                        CarrierId.All.IMSI_PREFIX_XPATTERN)),
                cursor.getString(cursor.getColumnIndexOrThrow(
                        CarrierId.All.ICCID_PREFIX)),
                cursor.getString(cursor.getColumnIndexOrThrow(CarrierId.All.GID1)),
                cursor.getString(cursor.getColumnIndexOrThrow(CarrierId.All.GID2)),
                cursor.getString(cursor.getColumnIndexOrThrow(CarrierId.All.PLMN)),
                cursor.getString(cursor.getColumnIndexOrThrow(CarrierId.All.SPN)),
                cursor.getString(cursor.getColumnIndexOrThrow(CarrierId.All.APN)),
                (TextUtils.isEmpty(certs) ? null : new ArrayList<>(Arrays.asList(certs))),
                cursor.getInt(cursor.getColumnIndexOrThrow(CarrierId.CARRIER_ID)),
                cursor.getString(cursor.getColumnIndexOrThrow(CarrierId.CARRIER_NAME)),
                cursor.getInt(cursor.getColumnIndexOrThrow(CarrierId.PARENT_CARRIER_ID)));
    }

    /**
     * carrier matching attributes with corresponding cid
     */
    public static class CarrierMatchingRule {
        /**
         * These scores provide the hierarchical relationship between the attributes, intended to
         * resolve conflicts in a deterministic way. The scores are constructed such that a match
         * from a higher tier will beat any subsequent match which does not match at that tier,
         * so MCCMNC beats everything else. This avoids problems when two (or more) carriers rule
         * matches as the score helps to find the best match uniquely. e.g.,
         * rule 1 {mccmnc, imsi} rule 2 {mccmnc, imsi, gid1} and rule 3 {mccmnc, imsi, gid2} all
         * matches with subscription data. rule 2 wins with the highest matching score.
         */
        private static final int SCORE_MCCMNC                   = 1 << 8;
        private static final int SCORE_IMSI_PREFIX              = 1 << 7;
        private static final int SCORE_ICCID_PREFIX             = 1 << 6;
        private static final int SCORE_GID1                     = 1 << 5;
        private static final int SCORE_GID2                     = 1 << 4;
        private static final int SCORE_PLMN                     = 1 << 3;
        private static final int SCORE_PRIVILEGE_ACCESS_RULE    = 1 << 2;
        private static final int SCORE_SPN                      = 1 << 1;
        private static final int SCORE_APN                      = 1 << 0;

        private static final int SCORE_INVALID                  = -1;

        // carrier matching attributes
        public final String mccMnc;
        public final String imsiPrefixPattern;
        public final String iccidPrefix;
        public final String gid1;
        public final String gid2;
        public final String plmn;
        public final String spn;
        public final String apn;
        // there can be multiple certs configured in the UICC
        public final List<String> privilegeAccessRule;

        // user-facing carrier name
        private String mName;
        // unique carrier id
        private int mCid;
        // unique parent carrier id
        private int mParentCid;

        private int mScore = 0;

        @VisibleForTesting
        public CarrierMatchingRule(String mccmnc, String imsiPrefixPattern, String iccidPrefix,
                String gid1, String gid2, String plmn, String spn, String apn,
                List<String> privilegeAccessRule, int cid, String name, int parentCid) {
            mccMnc = mccmnc;
            this.imsiPrefixPattern = imsiPrefixPattern;
            this.iccidPrefix = iccidPrefix;
            this.gid1 = gid1;
            this.gid2 = gid2;
            this.plmn = plmn;
            this.spn = spn;
            this.apn = apn;
            this.privilegeAccessRule = privilegeAccessRule;
            mCid = cid;
            mName = name;
            mParentCid = parentCid;
        }

        private CarrierMatchingRule(CarrierMatchingRule rule) {
            mccMnc = rule.mccMnc;
            imsiPrefixPattern = rule.imsiPrefixPattern;
            iccidPrefix = rule.iccidPrefix;
            gid1 = rule.gid1;
            gid2 = rule.gid2;
            plmn = rule.plmn;
            spn = rule.spn;
            apn = rule.apn;
            privilegeAccessRule = rule.privilegeAccessRule;
            mCid = rule.mCid;
            mName = rule.mName;
            mParentCid = rule.mParentCid;
        }

        // Calculate matching score. Values which aren't set in the rule are considered "wild".
        // All values in the rule must match in order for the subscription to be considered part of
        // the carrier. Otherwise, a invalid score -1 will be assigned. A match from a higher tier
        // will beat any subsequent match which does not match at that tier. When there are multiple
        // matches at the same tier, the match with highest score will be used.
        public void match(CarrierMatchingRule subscriptionRule) {
            mScore = 0;
            if (mccMnc != null) {
                if (!CarrierResolver.equals(subscriptionRule.mccMnc, mccMnc, false)) {
                    mScore = SCORE_INVALID;
                    return;
                }
                mScore += SCORE_MCCMNC;
            }
            if (imsiPrefixPattern != null) {
                if (!imsiPrefixMatch(subscriptionRule.imsiPrefixPattern, imsiPrefixPattern)) {
                    mScore = SCORE_INVALID;
                    return;
                }
                mScore += SCORE_IMSI_PREFIX;
            }
            if (iccidPrefix != null) {
                if (!iccidPrefixMatch(subscriptionRule.iccidPrefix, iccidPrefix)) {
                    mScore = SCORE_INVALID;
                    return;
                }
                mScore += SCORE_ICCID_PREFIX;
            }
            if (gid1 != null) {
                if (!gidMatch(subscriptionRule.gid1, gid1)) {
                    mScore = SCORE_INVALID;
                    return;
                }
                mScore += SCORE_GID1;
            }
            if (gid2 != null) {
                if (!gidMatch(subscriptionRule.gid2, gid2)) {
                    mScore = SCORE_INVALID;
                    return;
                }
                mScore += SCORE_GID2;
            }
            if (plmn != null) {
                if (!CarrierResolver.equals(subscriptionRule.plmn, plmn, true)) {
                    mScore = SCORE_INVALID;
                    return;
                }
                mScore += SCORE_PLMN;
            }
            if (spn != null) {
                if (!CarrierResolver.equals(subscriptionRule.spn, spn, true)) {
                    mScore = SCORE_INVALID;
                    return;
                }
                mScore += SCORE_SPN;
            }

            if (privilegeAccessRule != null && !privilegeAccessRule.isEmpty()) {
                if (!carrierPrivilegeRulesMatch(subscriptionRule.privilegeAccessRule,
                        privilegeAccessRule)) {
                    mScore = SCORE_INVALID;
                    return;
                }
                mScore += SCORE_PRIVILEGE_ACCESS_RULE;
            }

            if (apn != null) {
                if (!CarrierResolver.equals(subscriptionRule.apn, apn, true)) {
                    mScore = SCORE_INVALID;
                    return;
                }
                mScore += SCORE_APN;
            }
        }

        private boolean imsiPrefixMatch(String imsi, String prefixXPattern) {
            if (TextUtils.isEmpty(prefixXPattern)) return true;
            if (TextUtils.isEmpty(imsi)) return false;
            if (imsi.length() < prefixXPattern.length()) {
                return false;
            }
            for (int i = 0; i < prefixXPattern.length(); i++) {
                if ((prefixXPattern.charAt(i) != 'x') && (prefixXPattern.charAt(i) != 'X')
                        && (prefixXPattern.charAt(i) != imsi.charAt(i))) {
                    return false;
                }
            }
            return true;
        }

        private boolean iccidPrefixMatch(String iccid, String prefix) {
            if (iccid == null || prefix == null) {
                return false;
            }
            return iccid.startsWith(prefix);
        }

        // We are doing prefix and case insensitive match.
        // Ideally we should do full string match. However due to SIM manufacture issues
        // gid from some SIM might has garbage tail.
        private boolean gidMatch(String gidFromSim, String gid) {
            return (gidFromSim != null) && gidFromSim.toLowerCase().startsWith(gid.toLowerCase());
        }

        private boolean carrierPrivilegeRulesMatch(List<String> certsFromSubscription,
                                                   List<String> certs) {
            if (certsFromSubscription == null || certsFromSubscription.isEmpty()) {
                return false;
            }
            for (String cert : certs) {
                for (String certFromSubscription : certsFromSubscription) {
                    if (!TextUtils.isEmpty(cert)
                            && cert.equalsIgnoreCase(certFromSubscription)) {
                        return true;
                    }
                }
            }
            return false;
        }

        public String toString() {
            return "[CarrierMatchingRule] -"
                    + " mccmnc: " + mccMnc
                    + " gid1: " + gid1
                    + " gid2: " + gid2
                    + " plmn: " + plmn
                    + " imsi_prefix: " + imsiPrefixPattern
                    + " iccid_prefix" + iccidPrefix
                    + " spn: " + spn
                    + " privilege_access_rule: " + privilegeAccessRule
                    + " apn: " + apn
                    + " name: " + mName
                    + " cid: " + mCid
                    + " score: " + mScore;
        }
    }

    private CarrierMatchingRule getSubscriptionMatchingRule() {
        final String mccmnc = mTelephonyMgr.getSimOperatorNumericForPhone(mPhone.getPhoneId());
        final String iccid = mPhone.getIccSerialNumber();
        final String gid1 = mPhone.getGroupIdLevel1();
        final String gid2 = mPhone.getGroupIdLevel2();
        final String imsi = mPhone.getSubscriberId();
        final String plmn = mPhone.getPlmn();
        final String spn = mSpn;
        final String apn = mPreferApn;
        List<String> accessRules;
        // check if test override present
        if (!TextUtils.isEmpty(mTestOverrideCarrierPriviledgeRule)) {
            accessRules = new ArrayList<>(Arrays.asList(mTestOverrideCarrierPriviledgeRule));
        } else {
            accessRules = mTelephonyMgr.createForSubscriptionId(mPhone.getSubId())
                    .getCertsFromCarrierPrivilegeAccessRules();
        }

        if (VDBG) {
            logd("[matchSubscriptionCarrier]"
                    + " mnnmnc:" + mccmnc
                    + " gid1: " + gid1
                    + " gid2: " + gid2
                    + " imsi: " + Rlog.pii(LOG_TAG, imsi)
                    + " iccid: " + Rlog.pii(LOG_TAG, iccid)
                    + " plmn: " + plmn
                    + " spn: " + spn
                    + " apn: " + apn
                    + " accessRules: " + ((accessRules != null) ? accessRules : null));
        }
        return new CarrierMatchingRule(
                mccmnc, imsi, iccid, gid1, gid2, plmn, spn, apn, accessRules,
                TelephonyManager.UNKNOWN_CARRIER_ID, null,
                TelephonyManager.UNKNOWN_CARRIER_ID);
    }

    /**
     * find the best matching carrier from candidates with matched subscription MCCMNC.
     */
    private void matchSubscriptionCarrier() {
        if (!SubscriptionManager.isValidSubscriptionId(mPhone.getSubId())) {
            logd("[matchSubscriptionCarrier]" + "skip before sim records loaded");
            return;
        }
        int maxScore = CarrierMatchingRule.SCORE_INVALID;
        /**
         * For child-parent relationship. either child and parent have the same matching
         * score, or child's matching score > parents' matching score.
         */
        CarrierMatchingRule maxRule = null;
        CarrierMatchingRule maxRuleParent = null;
        /**
         * matching rule with mccmnc only. If mnoRule is found, then mno carrier id equals to the
         * cid from mnoRule. otherwise, mno carrier id is same as cid.
         */
        CarrierMatchingRule mnoRule = null;
        CarrierMatchingRule subscriptionRule = getSubscriptionMatchingRule();

        for (CarrierMatchingRule rule : mCarrierMatchingRulesOnMccMnc) {
            rule.match(subscriptionRule);
            if (rule.mScore > maxScore) {
                maxScore = rule.mScore;
                maxRule = rule;
                maxRuleParent = rule;
            } else if (maxScore > CarrierMatchingRule.SCORE_INVALID && rule.mScore == maxScore) {
                // to handle the case that child parent has the same matching score, we need to
                // differentiate who is child who is parent.
                if (rule.mParentCid == maxRule.mCid) {
                    maxRule = rule;
                } else if (maxRule.mParentCid == rule.mCid) {
                    maxRuleParent = rule;
                }
            }
            if (rule.mScore == CarrierMatchingRule.SCORE_MCCMNC) {
                mnoRule = rule;
            }
        }
        if (maxScore == CarrierMatchingRule.SCORE_INVALID) {
            logd("[matchSubscriptionCarrier - no match] cid: " + TelephonyManager.UNKNOWN_CARRIER_ID
                    + " name: " + null);
            updateCarrierIdAndName(TelephonyManager.UNKNOWN_CARRIER_ID, null,
                    TelephonyManager.UNKNOWN_CARRIER_ID, null,
                    TelephonyManager.UNKNOWN_CARRIER_ID);
        } else {
            // if there is a single matching result, check if this rule has parent cid assigned.
            if ((maxRule == maxRuleParent)
                    && maxRule.mParentCid != TelephonyManager.UNKNOWN_CARRIER_ID) {
                maxRuleParent = new CarrierMatchingRule(maxRule);
                maxRuleParent.mCid = maxRuleParent.mParentCid;
                maxRuleParent.mName = getCarrierNameFromId(maxRuleParent.mCid);
            }
            logd("[matchSubscriptionCarrier] specific cid: " + maxRule.mCid
                    + " specific name: " + maxRule.mName +" cid: " + maxRuleParent.mCid
                    + " name: " + maxRuleParent.mName);
            updateCarrierIdAndName(maxRuleParent.mCid, maxRuleParent.mName,
                    maxRule.mCid, maxRule.mName,
                    (mnoRule == null) ? maxRule.mCid : mnoRule.mCid);
        }

        /*
         * Write Carrier Identification Matching event, logging with the
         * carrierId, mccmnc, gid1 and carrier list version to differentiate below cases of metrics:
         * 1) unknown mccmnc - the Carrier Id provider contains no rule that matches the
         * read mccmnc.
         * 2) the Carrier Id provider contains some rule(s) that match the read mccmnc,
         * but the read gid1 is not matched within the highest-scored rule.
         * 3) successfully found a matched carrier id in the provider.
         * 4) use carrier list version to compare the unknown carrier ratio between each version.
         */
        String unknownGid1ToLog = ((maxScore & CarrierMatchingRule.SCORE_GID1) == 0
                && !TextUtils.isEmpty(subscriptionRule.gid1)) ? subscriptionRule.gid1 : null;
        String unknownMccmncToLog = ((maxScore == CarrierMatchingRule.SCORE_INVALID
                || (maxScore & CarrierMatchingRule.SCORE_GID1) == 0)
                && !TextUtils.isEmpty(subscriptionRule.mccMnc)) ? subscriptionRule.mccMnc : null;

        // pass subscription rule to metrics. scrub all possible PII before uploading.
        // only log apn if not user edited.
        String apn = (subscriptionRule.apn != null
                && !isPreferApnUserEdited(subscriptionRule.apn))
                ? subscriptionRule.apn : null;
        // only log first 7 bits of iccid
        String iccidPrefix = (subscriptionRule.iccidPrefix != null)
                && (subscriptionRule.iccidPrefix.length() >= 7)
                ? subscriptionRule.iccidPrefix.substring(0, 7) : subscriptionRule.iccidPrefix;
        // only log first 8 bits of imsi
        String imsiPrefix = (subscriptionRule.imsiPrefixPattern != null)
                && (subscriptionRule.imsiPrefixPattern.length() >= 8)
                ? subscriptionRule.imsiPrefixPattern.substring(0, 8)
                : subscriptionRule.imsiPrefixPattern;

        CarrierMatchingRule simInfo = new CarrierMatchingRule(
                subscriptionRule.mccMnc,
                imsiPrefix,
                iccidPrefix,
                subscriptionRule.gid1,
                subscriptionRule.gid2,
                subscriptionRule.plmn,
                subscriptionRule.spn,
                apn,
                subscriptionRule.privilegeAccessRule,
                -1, null, -1);

        TelephonyMetrics.getInstance().writeCarrierIdMatchingEvent(
                mPhone.getPhoneId(), getCarrierListVersion(), mCarrierId,
                unknownMccmncToLog, unknownGid1ToLog, simInfo);
    }

    public int getCarrierListVersion() {
        final Cursor cursor = mContext.getContentResolver().query(
                Uri.withAppendedPath(CarrierId.All.CONTENT_URI,
                "get_version"), null, null, null);
        cursor.moveToFirst();
        return cursor.getInt(0);
    }

    public int getCarrierId() {
        return mCarrierId;
    }
    /**
     * Returns fine-grained carrier id of the current subscription. Carrier ids with a valid parent
     * id are specific carrier ids.
     *
     * A specific carrier ID can represent the fact that a carrier may be in effect an aggregation
     * of other carriers (ie in an MVNO type scenario) where each of these specific carriers which
     * are used to make up the actual carrier service may have different carrier configurations.
     * A specific carrier ID could also be used, for example, in a scenario where a carrier requires
     * different carrier configuration for different service offering such as a prepaid plan.
     * e.g, {@link #getCarrierId()} will always return Tracfone (id 2022) for a Tracfone SIM, while
     * {@link #getSpecificCarrierId()} can return Tracfone AT&T or Tracfone T-Mobile based on the
     * IMSI from the current subscription.
     *
     * For carriers without any fine-grained carrier ids, return {@link #getCarrierId()}
     */
    public int getSpecificCarrierId() {
        return mSpecificCarrierId;
    }

    public String getCarrierName() {
        return mCarrierName;
    }

    public String getSpecificCarrierName() {
        return mSpecificCarrierName;
    }

    public int getMnoCarrierId() {
        return mMnoCarrierId;
    }

    /**
     * a util function to convert carrierIdentifier to the best matching carrier id.
     *
     * @return the best matching carrier id.
     */
    public static int getCarrierIdFromIdentifier(@NonNull Context context,
                                                 @NonNull CarrierIdentifier carrierIdentifier) {
        final String mccmnc = carrierIdentifier.getMcc() + carrierIdentifier.getMnc();
        final String gid1 = carrierIdentifier.getGid1();
        final String gid2 = carrierIdentifier.getGid2();
        final String imsi = carrierIdentifier.getImsi();
        final String spn = carrierIdentifier.getSpn();
        if (VDBG) {
            logd("[getCarrierIdFromIdentifier]"
                    + " mnnmnc:" + mccmnc
                    + " gid1: " + gid1
                    + " gid2: " + gid2
                    + " imsi: " + Rlog.pii(LOG_TAG, imsi)
                    + " spn: " + spn);
        }
        // assign null to other fields which are not supported by carrierIdentifier.
        CarrierMatchingRule targetRule =
                new CarrierMatchingRule(mccmnc, imsi, null, gid1, gid2, null,
                        spn, null, null,
                        TelephonyManager.UNKNOWN_CARRIER_ID_LIST_VERSION, null,
                        TelephonyManager.UNKNOWN_CARRIER_ID);

        int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
        int maxScore = CarrierMatchingRule.SCORE_INVALID;
        List<CarrierMatchingRule> rules = getCarrierMatchingRulesFromMccMnc(
                context, targetRule.mccMnc);
        for (CarrierMatchingRule rule : rules) {
            rule.match(targetRule);
            if (rule.mScore > maxScore) {
                maxScore = rule.mScore;
                carrierId = rule.mCid;
            }
        }
        return carrierId;
    }

    /**
     * a util function to convert {mccmnc, mvno_type, mvno_data} to all matching carrier ids.
     *
     * @return a list of id with matching {mccmnc, mvno_type, mvno_data}
     */
    public static List<Integer> getCarrierIdsFromApnQuery(@NonNull Context context,
                                                          String mccmnc, String mvnoCase,
                                                          String mvnoData) {
        String selection = CarrierId.All.MCCMNC + "=" + mccmnc;
        // build the proper query
        if ("spn".equals(mvnoCase) && mvnoData != null) {
            selection += " AND " + CarrierId.All.SPN + "='" + mvnoData + "'";
        } else if ("imsi".equals(mvnoCase) && mvnoData != null) {
            selection += " AND " + CarrierId.All.IMSI_PREFIX_XPATTERN + "='" + mvnoData + "'";
        } else if ("gid1".equals(mvnoCase) && mvnoData != null) {
            selection += " AND " + CarrierId.All.GID1 + "='" + mvnoData + "'";
        } else if ("gid2".equals(mvnoCase) && mvnoData != null) {
            selection += " AND " + CarrierId.All.GID2 + "='" + mvnoData +"'";
        } else {
            logd("mvno case empty or other invalid values");
        }

        List<Integer> ids = new ArrayList<>();
        try {
            Cursor cursor = context.getContentResolver().query(
                    CarrierId.All.CONTENT_URI,
                    /* projection */ null,
                    /* selection */ selection,
                    /* selectionArgs */ null, null);
            try {
                if (cursor != null) {
                    if (VDBG) {
                        logd("[getCarrierIdsFromApnQuery]- " + cursor.getCount()
                                + " Records(s) in DB");
                    }
                    while (cursor.moveToNext()) {
                        int cid = cursor.getInt(cursor.getColumnIndex(CarrierId.CARRIER_ID));
                        if (!ids.contains(cid)) {
                            ids.add(cid);
                        }
                    }
                }
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        } catch (Exception ex) {
            loge("[getCarrierIdsFromApnQuery]- ex: " + ex);
        }
        logd(selection + " " + ids);
        return ids;
    }

    // static helper function to get carrier id from mccmnc
    public static int getCarrierIdFromMccMnc(@NonNull Context context, String mccmnc) {
        try {
            Cursor cursor = context.getContentResolver().query(
                    CarrierId.All.CONTENT_URI,
                    /* projection */ null,
                    /* selection */ CarrierId.All.MCCMNC + "=? AND "
                            + CarrierId.All.GID1 + " is NULL AND "
                            + CarrierId.All.GID2 + " is NULL AND "
                            + CarrierId.All.IMSI_PREFIX_XPATTERN + " is NULL AND "
                            + CarrierId.All.SPN + " is NULL AND "
                            + CarrierId.All.ICCID_PREFIX + " is NULL AND "
                            + CarrierId.All.PLMN + " is NULL AND "
                            + CarrierId.All.PRIVILEGE_ACCESS_RULE + " is NULL AND "
                            + CarrierId.All.APN + " is NULL",
                    /* selectionArgs */ new String[]{mccmnc},
                    null);
            try {
                if (cursor != null) {
                    if (VDBG) {
                        logd("[getCarrierIdFromMccMnc]- " + cursor.getCount()
                                + " Records(s) in DB" + " mccmnc: " + mccmnc);
                    }
                    while (cursor.moveToNext()) {
                        return cursor.getInt(cursor.getColumnIndex(CarrierId.CARRIER_ID));
                    }
                }
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        } catch (Exception ex) {
            loge("[getCarrierIdFromMccMnc]- ex: " + ex);
        }
        return TelephonyManager.UNKNOWN_CARRIER_ID;
    }

    private static boolean equals(String a, String b, boolean ignoreCase) {
        if (a == null && b == null) return true;
        if (a != null && b != null) {
            return (ignoreCase) ? a.equalsIgnoreCase(b) : a.equals(b);
        }
        return false;
    }

    private static void logd(String str) {
        Rlog.d(LOG_TAG, str);
    }
    private static void loge(String str) {
        Rlog.e(LOG_TAG, str);
    }
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
        ipw.println("mCarrierResolverLocalLogs:");
        ipw.increaseIndent();
        mCarrierIdLocalLog.dump(fd, pw, args);
        ipw.decreaseIndent();

        ipw.println("mCarrierId: " + mCarrierId);
        ipw.println("mSpecificCarrierId: " + mSpecificCarrierId);
        ipw.println("mMnoCarrierId: " + mMnoCarrierId);
        ipw.println("mCarrierName: " + mCarrierName);
        ipw.println("mSpecificCarrierName: " + mSpecificCarrierName);
        ipw.println("carrier_list_version: " + getCarrierListVersion());

        ipw.println("mCarrierMatchingRules on mccmnc: "
                + mTelephonyMgr.getSimOperatorNumericForPhone(mPhone.getPhoneId()));
        ipw.increaseIndent();
        for (CarrierMatchingRule rule : mCarrierMatchingRulesOnMccMnc) {
            ipw.println(rule.toString());
        }
        ipw.decreaseIndent();

        ipw.println("mSpn: " + mSpn);
        ipw.println("mPreferApn: " + mPreferApn);
        ipw.flush();
    }
}
