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

Commit 0fdc0ee4 authored by Nathan Harold's avatar Nathan Harold Committed by android-build-merger
Browse files

Merge "Revert "Support Fetching IMSI MCC and MNC for RuimRecords.""

am: 587752f7

Change-Id: Icb6c04f876a08eec9e71b86af8484caaac5f6e4d
parents 59f57de1 587752f7
Loading
Loading
Loading
Loading
+72 −93
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.telephony.SubscriptionManager;
import android.text.TextUtils;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.MccTable;
@@ -85,11 +84,8 @@ public class RuimRecords extends IccRecords {
                + " mHomeNetworkId=" + mHomeNetworkId;
    }

    //Constants
    //MNC length in case of CSIM/RUIM IMSI is 2 as per spec C.S0065 section 5.2.2
    private static final int CSIM_IMSI_MNC_LENGTH = 2;

    // ***** Event Constants
    private static final int EVENT_GET_IMSI_DONE = 3;
    private static final int EVENT_GET_DEVICE_IDENTITY_DONE = 4;
    private static final int EVENT_GET_ICCID_DONE = 5;
    private static final int EVENT_GET_CDMA_SUBSCRIPTION_DONE = 10;
@@ -207,62 +203,15 @@ public class RuimRecords extends IccRecords {
        }
    }

    private int decodeImsiDigits(int digits, int length) {
    private int adjstMinDigits (int digits) {
        // Per C.S0005 section 2.3.1.
        for (int i = 0, denominator = 1; i < length; i++) {
            digits += denominator;
            if ((digits / denominator) % 10 == 0) {
                digits = digits - (10 * denominator);
            }
            denominator *= 10;
        }
        digits += 111;
        digits = (digits % 10 == 0)?(digits - 10):digits;
        digits = ((digits / 10) % 10 == 0)?(digits - 100):digits;
        digits = ((digits / 100) % 10 == 0)?(digits - 1000):digits;
        return digits;
    }

    /**
     * Decode utility to decode IMSI from data read from EF_IMSIM
     * Please refer to
     *       // C.S0065 section 5.2.2 for IMSI_M encoding
     *       // C.S0005 section 2.3.1 for MIN encoding in IMSI_M.
     */
    private String decodeImsi(byte[] data) {
        // Retrieve the MCC and digits 11 and 12
        int mcc_data = ((0x03 & data[9]) << 8) | (0xFF & data[8]);
        int mcc = decodeImsiDigits(mcc_data, 3);
        int digits_11_12_data = data[6] & 0x7f;
        int digits_11_12 = decodeImsiDigits(digits_11_12_data, 2);

        // Retrieve 10 MIN digits
        int first3digits = ((0x03 & data[2]) << 8) + (0xFF & data[1]);
        int second3digits = (((0xFF & data[5]) << 8) | (0xFF & data[4])) >> 6;
        int digit7 = 0x0F & (data[4] >> 2);
        if (digit7 > 0x09) digit7 = 0;
        int last3digits = ((0x03 & data[4]) << 8) | (0xFF & data[3]);

        first3digits = decodeImsiDigits(first3digits, 3);
        second3digits = decodeImsiDigits(second3digits, 3);
        last3digits = decodeImsiDigits(last3digits, 3);

        return new StringBuilder()
                .append(String.format(Locale.US, "%03d", mcc))
                .append(String.format(Locale.US, "%02d", digits_11_12))
                .append(String.format(Locale.US, "%03d", first3digits))
                .append(String.format(Locale.US, "%03d", second3digits))
                .append(String.format(Locale.US, "%d", digit7))
                .append(String.format(Locale.US, "%03d", last3digits))
                .toString();
    }

     /**
     * Introduce Generic API returns the 5 or 6 digit MCC/MNC
     * of the operator that provided the RUIM card.
     * Returns null of RUIM is not yet ready
     */
    @Override
    public String getOperatorNumeric() {
        return getRUIMOperatorNumeric();
    }

    /**
     * Returns the 5 or 6 digit MCC/MNC of the operator that
     *  provided the RUIM card. Returns null of RUIM is not yet ready
@@ -274,16 +223,17 @@ public class RuimRecords extends IccRecords {
            return null;
        }

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

        return imsi.substring(0, 3 + mncLen);
        // Guess the MNC length based on the MCC if we don't
        // have a valid value in ef[ad]

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

    // Refer to ETSI TS 102.221
@@ -419,8 +369,7 @@ public class RuimRecords extends IccRecords {
        }
    }

    @VisibleForTesting
    public class EfCsimImsimLoaded implements IccRecordLoaded {
    private class EfCsimImsimLoaded implements IccRecordLoaded {
        @Override
        public String getEfName() {
            return "EF_CSIM_IMSIM";
@@ -429,41 +378,31 @@ public class RuimRecords extends IccRecords {
        @Override
        public void onRecordLoaded(AsyncResult ar) {
            byte[] data = (byte[]) ar.result;

            if (data == null || data.length < 10) {
                log("Invalid IMSI from EF_CSIM_IMSIM " + IccUtils.bytesToHexString(data));
                mImsi = null;
                mMin = null;
                return;
            }
            if (DBG) log("CSIM_IMSIM=" + IccUtils.bytesToHexString(data) +
                    Rlog.pii(LOG_TAG, IccUtils.bytesToHexString(data)));

            if (VDBG) log("CSIM_IMSIM=" + IccUtils.bytesToHexString(data));
            // C.S0065 section 5.2.2 for IMSI_M encoding
            // C.S0005 section 2.3.1 for MIN encoding in IMSI_M.
            boolean provisioned = ((data[7] & 0x80) == 0x80);

            if (provisioned) {
                mImsi = decodeImsi(data);
                if (null != mImsi) {
                    mMin = mImsi.substring(5, 15);
                }
                log("IMSI: " + mImsi.substring(0, 5) + "xxxxxxxxx" +
                         Rlog.pii(LOG_TAG, mImsi.substring(0, 5)));

                int first3digits = ((0x03 & data[2]) << 8) + (0xFF & data[1]);
                int second3digits = (((0xFF & data[5]) << 8) | (0xFF & data[4])) >> 6;
                int digit7 = 0x0F & (data[4] >> 2);
                if (digit7 > 0x09) digit7 = 0;
                int last3digits = ((0x03 & data[4]) << 8) | (0xFF & data[3]);
                first3digits = adjstMinDigits(first3digits);
                second3digits = adjstMinDigits(second3digits);
                last3digits = adjstMinDigits(last3digits);

                StringBuilder builder = new StringBuilder();
                builder.append(String.format(Locale.US, "%03d", first3digits));
                builder.append(String.format(Locale.US, "%03d", second3digits));
                builder.append(String.format(Locale.US, "%d", digit7));
                builder.append(String.format(Locale.US, "%03d", last3digits));
                mMin = builder.toString();
                if (DBG) log("min present=" + mMin);
            } else {
                if (DBG) log("IMSI not provisioned in card");
                if (DBG) log("min not present");
            }

            //Update MccTable with the retrieved IMSI
            String operatorNumeric = getOperatorNumeric();
            if (operatorNumeric != null) {
                if(operatorNumeric.length() <= 6){
                    MccTable.updateMccMncConfiguration(mContext, operatorNumeric);
                }
            }

            mImsiReadyRegistrants.notifyRegistrants();
        }
    }

@@ -679,6 +618,43 @@ public class RuimRecords extends IccRecords {
                log("Event EVENT_GET_DEVICE_IDENTITY_DONE Received");
            break;

            /* IO events */
            case EVENT_GET_IMSI_DONE:
                isRecordLoadResponse = true;

                ar = (AsyncResult)msg.obj;
                if (ar.exception != null) {
                    loge("Exception querying IMSI, Exception:" + ar.exception);
                    break;
                }

                mImsi = (String) ar.result;

                // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more
                // than 15 (and usually 15).
                if (mImsi != null && (mImsi.length() < 6 || mImsi.length() > 15)) {
                    loge("invalid IMSI " + mImsi);
                    mImsi = null;
                }

                // FIXME: CSIM IMSI may not contain the MNC.
                if (false) {
                    log("IMSI: " + mImsi.substring(0, 6) + "xxxxxxxxx");

                    String operatorNumeric = getRUIMOperatorNumeric();
                    if (operatorNumeric != null) {
                        if (operatorNumeric.length() <= 6) {
                            log("update mccmnc=" + operatorNumeric);
                            MccTable.updateMccMncConfiguration(mContext, operatorNumeric);
                        }
                    }
                } else {
                    String operatorNumeric = getRUIMOperatorNumeric();
                    log("NO update mccmnc=" + operatorNumeric);
                }

            break;

            case EVENT_GET_CDMA_SUBSCRIPTION_DONE:
                ar = (AsyncResult)msg.obj;
                String localTemp[] = (String[])ar.result;
@@ -866,6 +842,9 @@ public class RuimRecords extends IccRecords {

        if (DBG) log("fetchRuimRecords " + mRecordsToLoad);

        mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));
        mRecordsToLoad++;

        mFh.loadEFTransparent(EF_ICCID,
                obtainMessage(EVENT_GET_ICCID_DONE));
        mRecordsToLoad++;
+0 −88
Original line number Diff line number Diff line
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *     * Neither the name of The Linux Foundation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

package com.android.internal.telephony.uicc;

import org.mockito.Mock;
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
import org.mockito.MockitoAnnotations;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.android.internal.telephony.TelephonyTest;

import android.content.Context;
import android.os.AsyncResult;
import android.os.HandlerThread;

public class RuimRecordsTest extends TelephonyTest {

    private RuimRecords mRuimRecords;

    private class RuimRecordsTestHandler extends HandlerThread {
        private RuimRecordsTestHandler(String name) {
            super(name);
        }

        @Override
        public void onLooperPrepared() {
            mRuimRecords = new RuimRecords(mUiccCardApplication3gpp2, mContext, mSimulatedCommands);
            setReady(true);
        }
    }

    @Before
    public void setUp() throws Exception {
        super.setUp(this.getClass().getSimpleName());
        new RuimRecordsTestHandler(TAG).start();
        waitUntilReady();
    }

    @After
    public void tearDown() throws Exception {
        super.tearDown();
    }

    @Test
    public void testCsimImsiLoaded() {
         RuimRecords.EfCsimImsimLoaded mImsiLoaded = mRuimRecords.new EfCsimImsimLoaded();
         AsyncResult ar = new AsyncResult(null, null, null);
         mImsiLoaded.onRecordLoaded(ar);
         String mccmnc = mRuimRecords.getOperatorNumeric();
         assertNull(mccmnc);

         byte[] byteArray = new byte[]{0,19,3,75,68,88,99,(byte)128,(byte)209,0};
         AsyncResult ar2 = new AsyncResult(null, byteArray, null);
         mImsiLoaded.onRecordLoaded(ar2);
         mccmnc = mRuimRecords.getOperatorNumeric();
         assertNotNull(mccmnc);
         assertEquals("31000", mccmnc);
    }
}