Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f4fd861 authored by sqian's avatar sqian Committed by shuoq
Browse files

Provide a machanism to override MVNO parameters below CarrierConfig

- maintain fake variables of imsi, gid1, gid2, and spn in IccRecord,
and add them into toString() and dump()
- provide a machanism to override Imsi, gid1, gid2, and spn during
sim/ruim record loading
- refactor the usages of getIMSI(), getGid1(), getGid2(),
and getServiceProviderName()
- fix potential crash issue in SIMRecord

Test: Manual
Bug: 32591388
Change-Id: I6dde2c29ca2f5c1dc55807e244260891ace08838
parent 9078d28b
Loading
Loading
Loading
Loading
+165 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 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.uicc;

import android.os.Environment;
import android.telephony.Rlog;
import android.util.Xml;

import com.android.internal.util.XmlUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;

/**
 * Provide a machanism to override MVNO paramteres under CarrierConfig through a config file.
 */
public class CarrierTestOverride {
    static final String LOG_TAG = "CarrierTestOverride";

    /**
     * Config file that can be created and adb-pushed by tester/developer
     *
     * Sample xml:
     * <carrierTestOverrides>
       <carrierTestOverride key="isInTestMode" value="true"/>
       <carrierTestOverride key="gid1" value="bae0000000000000"/>
       <carrierTestOverride key="gid2" value="ffffffffffffffff"/>
       <carrierTestOverride key="imsi" value="310010123456789"/>
       <carrierTestOverride key="spn" value="Verizon"/>
       </carrierTestOverrides>
     */
    static final String DATA_CARRIER_TEST_OVERRIDE_PATH =
            "/user_de/0/com.android.phone/files/carrier_test_conf.xml";
    static final String CARRIER_TEST_XML_HEADER = "carrierTestOverrides";
    static final String CARRIER_TEST_XML_SUBHEADER = "carrierTestOverride";
    static final String CARRIER_TEST_XML_ITEM_KEY = "key";
    static final String CARRIER_TEST_XML_ITEM_VALUE = "value";
    static final String CARRIER_TEST_XML_ITEM_KEY_STRING_ISINTESTMODE = "isInTestMode";
    static final String CARRIER_TEST_XML_ITEM_KEY_STRING_GID1 = "gid1";
    static final String CARRIER_TEST_XML_ITEM_KEY_STRING_GID2 = "gid2";
    static final String CARRIER_TEST_XML_ITEM_KEY_STRING_IMSI = "imsi";
    static final String CARRIER_TEST_XML_ITEM_KEY_STRING_SPN = "spn";

    private HashMap<String, String> mCarrierTestParamMap;

    CarrierTestOverride() {
        mCarrierTestParamMap = new HashMap<String, String>();
        loadCarrierTestOverrides();
    }

    boolean isInTestMode() {
        return mCarrierTestParamMap.containsKey(CARRIER_TEST_XML_ITEM_KEY_STRING_ISINTESTMODE)
                && mCarrierTestParamMap.get(CARRIER_TEST_XML_ITEM_KEY_STRING_ISINTESTMODE)
                .equals("true");
    }

    String getFakeSpn() {
        try {
            String spn = mCarrierTestParamMap.get(CARRIER_TEST_XML_ITEM_KEY_STRING_SPN);
            Rlog.d(LOG_TAG, "reading spn from CarrierTestConfig file: " + spn);
            return spn;
        } catch (NullPointerException e) {
            Rlog.w(LOG_TAG, "No spn in CarrierTestConfig file ");
            return null;
        }
    }

    String getFakeIMSI() {
        try {
            String imsi = mCarrierTestParamMap.get(CARRIER_TEST_XML_ITEM_KEY_STRING_IMSI);
            Rlog.d(LOG_TAG, "reading imsi from CarrierTestConfig file: " + imsi);
            return imsi;
        } catch (NullPointerException e) {
            Rlog.w(LOG_TAG, "No imsi in CarrierTestConfig file ");
            return null;
        }
    }

    String getFakeGid1() {
        try {
            String gid1 = mCarrierTestParamMap.get(CARRIER_TEST_XML_ITEM_KEY_STRING_GID1);
            Rlog.d(LOG_TAG, "reading gid1 from CarrierTestConfig file: " + gid1);
            return gid1;
        } catch (NullPointerException e) {
            Rlog.w(LOG_TAG, "No gid1 in CarrierTestConfig file ");
            return null;
        }
    }

    String getFakeGid2() {
        try {
            String gid2 = mCarrierTestParamMap.get(CARRIER_TEST_XML_ITEM_KEY_STRING_GID2);
            Rlog.d(LOG_TAG, "reading gid2 from CarrierTestConfig file: " + gid2);
            return gid2;
        } catch (NullPointerException e) {
            Rlog.w(LOG_TAG, "No gid2 in CarrierTestConfig file ");
            return null;
        }
    }

    private void loadCarrierTestOverrides() {

        FileReader carrierTestConfigReader;

        File carrierTestConfigFile = new File(Environment.getDataDirectory(),
                DATA_CARRIER_TEST_OVERRIDE_PATH);

        try {
            carrierTestConfigReader = new FileReader(carrierTestConfigFile);
            Rlog.d(LOG_TAG, "CarrierTestConfig file Modified Timestamp: "
                    + carrierTestConfigFile.lastModified());
        } catch (FileNotFoundException e) {
            Rlog.w(LOG_TAG, "Can not open " + carrierTestConfigFile.getAbsolutePath());
            return;
        }

        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(carrierTestConfigReader);

            XmlUtils.beginDocument(parser, CARRIER_TEST_XML_HEADER);

            while (true) {
                XmlUtils.nextElement(parser);

                String name = parser.getName();
                if (!CARRIER_TEST_XML_SUBHEADER.equals(name)) {
                    break;
                }

                String key = parser.getAttributeValue(null, CARRIER_TEST_XML_ITEM_KEY);
                String value = parser.getAttributeValue(null, CARRIER_TEST_XML_ITEM_VALUE);

                Rlog.d(LOG_TAG,
                        "extracting key-values from CarrierTestConfig file: " + key + "|" + value);
                mCarrierTestParamMap.put(key, value);
            }
            carrierTestConfigReader.close();
        } catch (XmlPullParserException e) {
            Rlog.w(LOG_TAG, "Exception in carrier_test_conf parser " + e);
        } catch (IOException e) {
            Rlog.w(LOG_TAG, "Exception in carrier_test_conf parser " + e);
        }
    }
}
+53 −5
Original line number Diff line number Diff line
@@ -78,15 +78,20 @@ public abstract class IccRecords extends Handler implements IccConstants {
    protected String mNewVoiceMailTag = null;
    protected boolean mIsVoiceMailFixed = false;
    protected String mImsi;
    protected String mFakeImsi;
    private IccIoResult auth_rsp;

    protected int mMncLength = UNINITIALIZED;
    protected int mMailboxIndex = 0; // 0 is no mailbox dailing number associated

    private String mSpn;
    private String mFakeSpn;

    protected String mGid1;
    protected String mFakeGid1;
    protected String mGid2;
    protected String mFakeGid2;

    protected String mPrefLang;

    protected PlmnActRecord[] mHplmnActRecords;
@@ -98,6 +103,8 @@ public abstract class IccRecords extends Handler implements IccConstants {

    private final Object mLock = new Object();

    CarrierTestOverride mCarrierTestOverride;

    //Arbitrary offset for the Handler
    protected static final int HANDLER_ACTION_BASE = 0x12E500;
    protected static final int HANDLER_ACTION_NONE = HANDLER_ACTION_BASE + 0;
@@ -157,9 +164,13 @@ public abstract class IccRecords extends Handler implements IccConstants {
                + " isVoiceMailFixed=" + mIsVoiceMailFixed
                + " mImsi=" + ((mImsi != null) ?
                mImsi.substring(0, 6) + Rlog.pii(VDBG, mImsi.substring(6)) : "null")
                + (mCarrierTestOverride.isInTestMode()
                ? (" mFakeImsi=" + ((mFakeImsi != null) ? mFakeImsi : "null")) : "")
                + " mncLength=" + mMncLength
                + " mailboxIndex=" + mMailboxIndex
                + " spn=" + mSpn;
                + " spn=" + mSpn
                + (mCarrierTestOverride.isInTestMode()
                ? (" mFakeSpn=" + ((mFakeSpn != null) ? mFakeSpn : "null")) : "");

    }

@@ -187,6 +198,22 @@ public abstract class IccRecords extends Handler implements IccConstants {
        mParentApp = app;
        mTelephonyManager = (TelephonyManager) mContext.getSystemService(
                Context.TELEPHONY_SERVICE);

        mCarrierTestOverride = new CarrierTestOverride();

        if (mCarrierTestOverride.isInTestMode()) {
            mFakeImsi = mCarrierTestOverride.getFakeIMSI();
            log("load mFakeImsi: " + mFakeImsi);

            mFakeGid1 = mCarrierTestOverride.getFakeGid1();
            log("load mFakeGid1: " + mFakeGid1);

            mFakeGid2 = mCarrierTestOverride.getFakeGid2();
            log("load mFakeGid2: " + mFakeGid2);

            mFakeSpn = mCarrierTestOverride.getFakeSpn();
            log("load mFakeSpn: " + mFakeSpn);
        }
    }

    /**
@@ -279,7 +306,7 @@ public abstract class IccRecords extends Handler implements IccConstants {
        Registrant r = new Registrant(h, what, obj);
        mImsiReadyRegistrants.add(r);

        if (mImsi != null) {
        if (getIMSI() != null) {
            r.notifyRegistrant(new AsyncResult(null, null, null));
        }
    }
@@ -325,7 +352,11 @@ public abstract class IccRecords extends Handler implements IccConstants {
     * @return null if SIM is not yet ready or unavailable
     */
    public String getIMSI() {
        return null;
        if (mCarrierTestOverride.isInTestMode() && mFakeImsi != null) {
            return mFakeImsi;
        } else {
            return mImsi;
        }
    }

    /**
@@ -356,7 +387,11 @@ public abstract class IccRecords extends Handler implements IccConstants {
     * @return null if SIM is not yet ready
     */
    public String getGid1() {
        return null;
        if (mCarrierTestOverride.isInTestMode() && mFakeGid1 != null) {
            return mFakeGid1;
        } else {
            return mGid1;
        }
    }

    /**
@@ -364,7 +399,11 @@ public abstract class IccRecords extends Handler implements IccConstants {
     * @return null if SIM is not yet ready
     */
    public String getGid2() {
        return null;
        if (mCarrierTestOverride.isInTestMode() && mFakeGid2 != null) {
            return mFakeGid2;
        } else {
            return mGid2;
        }
    }

    public void setMsisdnNumber(String alphaTag, String number,
@@ -390,6 +429,9 @@ public abstract class IccRecords extends Handler implements IccConstants {
     * @return null if SIM is not yet ready or no RUIM entry
     */
    public String getServiceProviderName() {
        if (mCarrierTestOverride.isInTestMode() && mFakeSpn != null) {
            return mFakeSpn;
        }
        String providerName = mSpn;

        // Check for null pointers, mParentApp can be null after dispose,
@@ -777,9 +819,15 @@ public abstract class IccRecords extends Handler implements IccConstants {
        pw.println(" mIsVoiceMailFixed=" + mIsVoiceMailFixed);
        pw.println(" mImsi=" + ((mImsi != null) ?
                mImsi.substring(0, 6) + Rlog.pii(VDBG, mImsi.substring(6)) : "null"));
        if (mCarrierTestOverride.isInTestMode()) {
            pw.println(" mFakeImsi=" + ((mFakeImsi != null) ? mFakeImsi : "null"));
        }
        pw.println(" mMncLength=" + mMncLength);
        pw.println(" mMailboxIndex=" + mMailboxIndex);
        pw.println(" mSpn=" + mSpn);
        if (mCarrierTestOverride.isInTestMode()) {
            pw.println(" mFakeSpn=" + ((mFakeSpn != null) ? mFakeSpn : "null"));
        }
        pw.flush();
    }
}
+19 −20
Original line number Diff line number Diff line
@@ -18,31 +18,31 @@ package com.android.internal.telephony.uicc;

import static com.android.internal.telephony.TelephonyProperties.PROPERTY_TEST_CSIM;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
import android.content.Context;
import android.content.res.Resources;
import android.os.AsyncResult;
import android.os.Message;
import android.os.SystemProperties;
import android.telephony.Rlog;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.Rlog;
import android.text.TextUtils;
import android.util.Log;
import android.content.res.Resources;

import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.MccTable;
import com.android.internal.telephony.SubscriptionController;

import com.android.internal.telephony.cdma.sms.UserData;
import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
import com.android.internal.util.BitwiseInputStream;

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

/**
 * {@hide}
 */
@@ -153,11 +153,6 @@ public class RuimRecords extends IccRecords {
        mRecordsRequested = false;
    }

    @Override
    public String getIMSI() {
        return mImsi;
    }

    public String getMdnNumber() {
        return mMyMobileNumber;
    }
@@ -215,21 +210,23 @@ public class RuimRecords extends IccRecords {
     *  provided the RUIM card. Returns null of RUIM is not yet ready
     */
    public String getRUIMOperatorNumeric() {
        if (mImsi == null) {
        String imsi = getIMSI();

        if (imsi == null) {
            return null;
        }

        if (mMncLength != UNINITIALIZED && mMncLength != UNKNOWN) {
            // Length = length of MCC + length of MNC
            // length of mcc = 3 (3GPP2 C.S0005 - Section 2.3)
            return mImsi.substring(0, 3 + mMncLength);
            return imsi.substring(0, 3 + mMncLength);
        }

        // Guess the MNC length based on the MCC if we don't
        // have a valid value in ef[ad]

        int mcc = Integer.parseInt(mImsi.substring(0,3));
        return mImsi.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
        int mcc = Integer.parseInt(imsi.substring(0, 3));
        return imsi.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
    }

    // Refer to ETSI TS 102.221
@@ -774,12 +771,14 @@ public class RuimRecords extends IccRecords {
                log("onAllRecordsLoaded empty 'gsm.sim.operator.numeric' skipping");
            }

            if (!TextUtils.isEmpty(mImsi)) {
                log("onAllRecordsLoaded set mcc imsi=" + (VDBG ? ("=" + mImsi) : ""));
            String imsi = getIMSI();

            if (!TextUtils.isEmpty(imsi)) {
                log("onAllRecordsLoaded set mcc imsi=" + (VDBG ? ("=" + imsi) : ""));
                mTelephonyManager.setSimCountryIsoForPhone(
                        mParentApp.getPhoneId(),
                        MccTable.countryCodeForMcc(
                        Integer.parseInt(mImsi.substring(0,3))));
                        Integer.parseInt(imsi.substring(0, 3))));
            } else {
                log("onAllRecordsLoaded empty imsi skipping setting mcc");
            }
+52 −42
Original line number Diff line number Diff line
@@ -295,32 +295,13 @@ public class SIMRecords extends IccRecords {
        mRecordsRequested = false;
    }


    //***** Public Methods

    /**
     * {@inheritDoc}
     */
    @Override
    public String getIMSI() {
        return mImsi;
    }

    @Override
    public String getMsisdnNumber() {
        return mMsisdn;
    }

    @Override
    public String getGid1() {
        return mGid1;
    }

    @Override
    public String getGid2() {
        return mGid2;
    }

    @Override
    public UsimServiceTable getUsimServiceTable() {
        return mUsimServiceTable;
@@ -638,7 +619,8 @@ public class SIMRecords extends IccRecords {
     */
    @Override
    public String getOperatorNumeric() {
        if (mImsi == null) {
        String imsi = getIMSI();
        if (imsi == null) {
            log("getOperatorNumeric: IMSI == null");
            return null;
        }
@@ -649,7 +631,11 @@ public class SIMRecords extends IccRecords {

        // Length = length of MCC + length of MNC
        // length of mcc = 3 (TS 23.003 Section 2.2)
        return mImsi.substring(0, 3 + mMncLength);
        if (imsi.length() >= 3 + mMncLength) {
            return imsi.substring(0, 3 + mMncLength);
        } else {
            return null;
        }
    }

    // ***** Overridden from Handler
@@ -699,11 +685,17 @@ public class SIMRecords extends IccRecords {
                    }

                    log("IMSI: mMncLength=" + mMncLength);
                    log("IMSI: " + mImsi.substring(0, 6) + Rlog.pii(LOG_TAG, mImsi.substring(6)));

                    if (mImsi != null && mImsi.length() >= 6) {
                        log("IMSI: " + mImsi.substring(0, 6)
                                + Rlog.pii(LOG_TAG, mImsi.substring(6)));
                    }

                    String imsi = getIMSI();

                    if (((mMncLength == UNKNOWN) || (mMncLength == 2))
                            && ((mImsi != null) && (mImsi.length() >= 6))) {
                        String mccmncCode = mImsi.substring(0, 6);
                            && ((imsi != null) && (imsi.length() >= 6))) {
                        String mccmncCode = imsi.substring(0, 6);
                        for (String mccmnc : MCCMNC_CODES_HAVING_3DIGITS_MNC) {
                            if (mccmnc.equals(mccmncCode)) {
                                mMncLength = 3;
@@ -717,7 +709,7 @@ public class SIMRecords extends IccRecords {
                        // the SIM has told us all it knows, but it didn't know the mnc length.
                        // guess using the mcc
                        try {
                            int mcc = Integer.parseInt(mImsi.substring(0, 3));
                            int mcc = Integer.parseInt(imsi.substring(0, 3));
                            mMncLength = MccTable.smallestDigitsMccForMnc(mcc);
                            log("setting2 mMncLength=" + mMncLength);
                        } catch (NumberFormatException e) {
@@ -726,12 +718,13 @@ public class SIMRecords extends IccRecords {
                        }
                    }

                    if (mMncLength != UNKNOWN && mMncLength != UNINITIALIZED) {
                        log("update mccmnc=" + mImsi.substring(0, 3 + mMncLength));
                    if (mMncLength != UNKNOWN && mMncLength != UNINITIALIZED
                            && imsi.length() >= 3 + mMncLength) {
                        log("update mccmnc=" + imsi.substring(0, 3 + mMncLength));
                        // finally have both the imsi and the mncLength and
                        // can parse the imsi properly
                        MccTable.updateMccMncConfiguration(mContext,
                                mImsi.substring(0, 3 + mMncLength), false);
                                imsi.substring(0, 3 + mMncLength), false);
                    }
                    mImsiReadyRegistrants.notifyRegistrants();
                    break;
@@ -955,10 +948,14 @@ public class SIMRecords extends IccRecords {
                            log("setting5 mMncLength=" + mMncLength);
                        }
                    } finally {

                        // IMSI could be a value reading from Sim or a fake IMSI if in the test mode
                        imsi = getIMSI();

                        if (((mMncLength == UNINITIALIZED) || (mMncLength == UNKNOWN)
                                    || (mMncLength == 2)) && ((mImsi != null)
                                    && (mImsi.length() >= 6))) {
                            String mccmncCode = mImsi.substring(0, 6);
                                    || (mMncLength == 2)) && ((imsi != null)
                                    && (imsi.length() >= 6))) {
                            String mccmncCode = imsi.substring(0, 6);
                            log("mccmncCode=" + mccmncCode);
                            for (String mccmnc : MCCMNC_CODES_HAVING_3DIGITS_MNC) {
                                if (mccmnc.equals(mccmncCode)) {
@@ -970,9 +967,9 @@ public class SIMRecords extends IccRecords {
                        }

                        if (mMncLength == UNKNOWN || mMncLength == UNINITIALIZED) {
                            if (mImsi != null) {
                            if (imsi != null) {
                                try {
                                    int mcc = Integer.parseInt(mImsi.substring(0, 3));
                                    int mcc = Integer.parseInt(imsi.substring(0, 3));

                                    mMncLength = MccTable.smallestDigitsMccForMnc(mcc);
                                    log("setting7 mMncLength=" + mMncLength);
@@ -987,12 +984,13 @@ public class SIMRecords extends IccRecords {
                                        + "mMncLength=" + mMncLength);
                            }
                        }
                        if (mImsi != null && mMncLength != UNKNOWN) {
                        if (imsi != null && mMncLength != UNKNOWN
                                && imsi.length() >= 3 + mMncLength) {
                            // finally have both imsi and the length of the mnc and can parse
                            // the imsi properly
                            log("update mccmnc=" + mImsi.substring(0, 3 + mMncLength));
                            log("update mccmnc=" + imsi.substring(0, 3 + mMncLength));
                            MccTable.updateMccMncConfiguration(mContext,
                                    mImsi.substring(0, 3 + mMncLength), false);
                                    imsi.substring(0, 3 + mMncLength), false);
                        }
                    }
                    break;
@@ -1248,7 +1246,9 @@ public class SIMRecords extends IccRecords {
                        mGid1 = null;
                        break;
                    }

                    mGid1 = IccUtils.bytesToHexString(data);

                    log("GID1: " + mGid1);

                    break;
@@ -1263,7 +1263,9 @@ public class SIMRecords extends IccRecords {
                        mGid2 = null;
                        break;
                    }

                    mGid2 = IccUtils.bytesToHexString(data);

                    log("GID2: " + mGid2);

                    break;
@@ -1597,11 +1599,13 @@ public class SIMRecords extends IccRecords {
            log("onAllRecordsLoaded empty 'gsm.sim.operator.numeric' skipping");
        }

        if (!TextUtils.isEmpty(mImsi)) {
            log("onAllRecordsLoaded set mcc imsi" + (VDBG ? ("=" + mImsi) : ""));
        String imsi = getIMSI();

        if (!TextUtils.isEmpty(imsi) && imsi.length() >= 3) {
            log("onAllRecordsLoaded set mcc imsi" + (VDBG ? ("=" + imsi) : ""));
            mTelephonyManager.setSimCountryIsoForPhone(
                    mParentApp.getPhoneId(), MccTable.countryCodeForMcc(
                    Integer.parseInt(mImsi.substring(0,3))));
                    Integer.parseInt(imsi.substring(0, 3))));
        } else {
            log("onAllRecordsLoaded empty imsi skipping setting mcc");
        }
@@ -2158,7 +2162,13 @@ public class SIMRecords extends IccRecords {
        pw.println(" mPnnHomeName=" + mPnnHomeName);
        pw.println(" mUsimServiceTable=" + mUsimServiceTable);
        pw.println(" mGid1=" + mGid1);
        if (mCarrierTestOverride.isInTestMode()) {
            pw.println(" mFakeGid1=" + ((mFakeGid1 != null) ? mFakeGid1 : "null"));
        }
        pw.println(" mGid2=" + mGid2);
        if (mCarrierTestOverride.isInTestMode()) {
            pw.println(" mFakeGid2=" + ((mFakeGid2 != null) ? mFakeGid2 : "null"));
        }
        pw.println(" mPlmnActRecords[]=" + Arrays.toString(mPlmnActRecords));
        pw.println(" mOplmnActRecords[]=" + Arrays.toString(mOplmnActRecords));
        pw.println(" mHplmnActRecords[]=" + Arrays.toString(mHplmnActRecords));