From f8f8d5a1f6f50739b00374aaed9c5eb9882484f5 Mon Sep 17 00:00:00 2001 From: Sneh Bansal Date: Mon, 5 Feb 2018 12:14:06 +0530 Subject: [PATCH 1/3] Fix wrong APN list issue for multimode SIM cards. For multimode cards with CSIM, USIM apps, if RUIMRecords are loaded first, then APNs will be read with operator numeric from RUIMRecords, leading to data call issues with wrong APNs. Add fix to wait for SIMRecords loaded event to create APN list. Change-Id: Ibb90188dfbb8270844703a7a271e260bae171755 CRs-Fixed: 2178427 --- .../internal/telephony/GsmCdmaPhone.java | 5 +++ .../com/android/internal/telephony/Phone.java | 5 +++ .../telephony/dataconnection/DcTracker.java | 34 +++++++++++++++---- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java index 06040d623b..05ba09cd52 100644 --- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java +++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java @@ -2890,6 +2890,11 @@ public class GsmCdmaPhone extends Phone { } } + @Override + public SIMRecords getSIMRecords() { + return mSimRecords; + } + private void processIccRecordEvents(int eventCode) { switch (eventCode) { case IccRecords.EVENT_CFI: diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java index eddf121ae0..c830316886 100644 --- a/src/java/com/android/internal/telephony/Phone.java +++ b/src/java/com/android/internal/telephony/Phone.java @@ -82,6 +82,7 @@ import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType; import com.android.internal.telephony.uicc.IccFileHandler; import com.android.internal.telephony.uicc.IccRecords; import com.android.internal.telephony.uicc.IsimRecords; +import com.android.internal.telephony.uicc.SIMRecords; import com.android.internal.telephony.uicc.UiccCard; import com.android.internal.telephony.uicc.UiccCardApplication; import com.android.internal.telephony.uicc.UiccController; @@ -4109,6 +4110,10 @@ public abstract class Phone extends Handler implements PhoneInternalInterface { return RIL.RADIO_HAL_VERSION_UNKNOWN; } + public SIMRecords getSIMRecords() { + return null; + } + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("Phone: subId=" + getSubId()); pw.println(" mPhoneId=" + mPhoneId); diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java index 6a30c476ab..9ff06b5013 100644 --- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java +++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java @@ -111,6 +111,8 @@ import com.android.internal.telephony.dataconnection.DataConnectionReasons.DataD import com.android.internal.telephony.dataconnection.DataEnabledSettings.DataEnabledChangedReason; import com.android.internal.telephony.metrics.TelephonyMetrics; import com.android.internal.telephony.uicc.IccRecords; +import com.android.internal.telephony.uicc.RuimRecords; +import com.android.internal.telephony.uicc.SIMRecords; import com.android.internal.telephony.uicc.UiccController; import com.android.internal.util.ArrayUtils; import com.android.internal.util.AsyncChannel; @@ -232,6 +234,7 @@ public class DcTracker extends Handler { private final TelephonyManager mTelephonyManager; private final AlarmManager mAlarmManager; + private SIMRecords mSimRecords; /* Currently requested APN type (TODO: This should probably be a parameter not a member) */ private int mRequestedApnType = ApnSetting.TYPE_DEFAULT; @@ -250,6 +253,8 @@ public class DcTracker extends Handler { // Default sent packets without ack which triggers initial recovery steps private static final int NUMBER_SENT_PACKETS_OF_HANG = 10; + private static final int EVENT_SIM_RECORDS_LOADED = 100; + // Default for the data stall alarm while non-aggressive stall detection private static final int DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS_DEFAULT = 1000 * 60 * 6; // Default for the data stall alarm for aggressive stall detection @@ -3550,6 +3555,17 @@ public class DcTracker extends Handler { return null; } + void onRecordsLoaded() { + // If onRecordsLoadedOrSubIdChanged() is not called here, it should be called on + // onSubscriptionsChanged() when a valid subId is available. + int subId = mPhone.getSubId(); + if (mSubscriptionManager.isActiveSubId(subId)) { + onRecordsLoadedOrSubIdChanged(); + } else { + log("Ignoring EVENT_RECORDS_LOADED as subId is not valid: " + subId); + } + } + @Override public void handleMessage (Message msg) { if (VDBG) log("handleMessage msg=" + msg); @@ -3561,13 +3577,19 @@ public class DcTracker extends Handler { int requestType; switch (msg.what) { case DctConstants.EVENT_RECORDS_LOADED: - // If onRecordsLoadedOrSubIdChanged() is not called here, it should be called on - // onSubscriptionsChanged() when a valid subId is available. - int subId = mPhone.getSubId(); - if (mSubscriptionManager.isActiveSubId(subId)) { - onRecordsLoadedOrSubIdChanged(); + mSimRecords = mPhone.getSIMRecords(); + if ((mIccRecords.get() instanceof RuimRecords) && (mSimRecords != null)) { + mSimRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null); } else { - log("Ignoring EVENT_RECORDS_LOADED as subId is not valid: " + subId); + onRecordsLoaded(); + } + break; + + case EVENT_SIM_RECORDS_LOADED: + onRecordsLoaded(); + if (mSimRecords != null) { + mSimRecords.unregisterForRecordsLoaded(this); + mSimRecords = null; } break; -- GitLab From 7e982e13247252d331daf5c3e10116fa3ca84891 Mon Sep 17 00:00:00 2001 From: Mengjun Leng Date: Thu, 5 Sep 2019 12:35:17 +0800 Subject: [PATCH 2/3] Fetching IMSI from RUIM properly Regarding to multi-mode SIM, the AID might be empty, so that IMSI is read from a wrong application. To fix it, parse IMSI from EF file to overwrite the IMSI if it is empty. Change-Id: I61723aa4db73d136e72dad37a3b6db4dc77e0e4b CRs-Fixed: 2525186 --- .../internal/telephony/uicc/RuimRecords.java | 96 +++++++++++++------ .../internal/telephony/uicc/UiccProfile.java | 10 +- .../telephony/uicc/RuimRecordsTest.java | 88 +++++++++++++++++ 3 files changed, 159 insertions(+), 35 deletions(-) create mode 100644 tests/telephonytests/src/com/android/internal/telephony/uicc/RuimRecordsTest.java diff --git a/src/java/com/android/internal/telephony/uicc/RuimRecords.java b/src/java/com/android/internal/telephony/uicc/RuimRecords.java index ff4aad8fe7..832349438a 100644 --- a/src/java/com/android/internal/telephony/uicc/RuimRecords.java +++ b/src/java/com/android/internal/telephony/uicc/RuimRecords.java @@ -30,6 +30,7 @@ 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; @@ -208,16 +209,6 @@ public class RuimRecords extends IccRecords { } } - @UnsupportedAppUsage - private int adjstMinDigits (int digits) { - // Per C.S0005 section 2.3.1. - 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; - } - /** * Returns the 5 or 6 digit MCC/MNC of the operator that * provided the RUIM card. Returns null of RUIM is not yet ready @@ -376,7 +367,8 @@ public class RuimRecords extends IccRecords { } } - private class EfCsimImsimLoaded implements IccRecordLoaded { + @VisibleForTesting + public class EfCsimImsimLoaded implements IccRecordLoaded { @Override public String getEfName() { return "EF_CSIM_IMSIM"; @@ -385,32 +377,75 @@ public class RuimRecords extends IccRecords { @Override public void onRecordLoaded(AsyncResult ar) { byte[] data = (byte[]) ar.result; - if (VDBG) log("CSIM_IMSIM=" + IccUtils.bytesToHexString(data)); + if (data == null || data.length < 10) { + if (DBG) log("Invalid IMSI from EF_CSIM_IMSIM"); + return; + } + if (DBG) Rlog.pii(LOG_TAG, 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) { - 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(); + final String imsi = decodeImsi(data); + if (TextUtils.isEmpty(mImsi)) { + mImsi = imsi; + if (DBG) log("IMSI=" + Rlog.pii(LOG_TAG, mImsi)); + } + if (null != imsi) { + mMin = imsi.substring(5, 15); + } if (DBG) log("min present=" + Rlog.pii(LOG_TAG, mMin)); } else { if (DBG) log("min not present"); } } + + private int decodeImsiDigits(int digits, int length) { + // 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; + } + 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); + + StringBuilder builder = new StringBuilder(); + builder.append(String.format(Locale.US, "%03d", mcc)); + builder.append(String.format(Locale.US, "%02d", digits_11_12)); + 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)); + return builder.toString(); + } } private class EfCsimCdmaHomeLoaded implements IccRecordLoaded { @@ -852,8 +887,11 @@ public class RuimRecords extends IccRecords { if (DBG) log("fetchRuimRecords " + mRecordsToLoad); - mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE)); - mRecordsToLoad++; + if (!TextUtils.isEmpty(mParentApp.getAid()) + || mParentApp.getUiccProfile().getNumApplications() <= 1) { + mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE)); + mRecordsToLoad++; + } mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE)); diff --git a/src/java/com/android/internal/telephony/uicc/UiccProfile.java b/src/java/com/android/internal/telephony/uicc/UiccProfile.java index e34f99d5ff..a1a07c41ba 100644 --- a/src/java/com/android/internal/telephony/uicc/UiccProfile.java +++ b/src/java/com/android/internal/telephony/uicc/UiccProfile.java @@ -98,6 +98,7 @@ public class UiccProfile extends IccCard { private int mGsmUmtsSubscriptionAppIndex; private int mCdmaSubscriptionAppIndex; private int mImsSubscriptionAppIndex; + private int mApplicationCount; private UiccCardApplication[] mUiccApplications = new UiccCardApplication[IccCardStatus.CARD_MAX_APPS]; private Context mContext; @@ -955,6 +956,7 @@ public class UiccProfile extends IccCard { mGsmUmtsSubscriptionAppIndex = ics.mGsmUmtsSubscriptionAppIndex; mCdmaSubscriptionAppIndex = ics.mCdmaSubscriptionAppIndex; mImsSubscriptionAppIndex = ics.mImsSubscriptionAppIndex; + mApplicationCount = ics.mApplications.length; mContext = c; mCi = ci; mTelephonyManager = (TelephonyManager) mContext.getSystemService( @@ -1520,13 +1522,9 @@ public class UiccProfile extends IccCard { * Returns number of applications on this card */ public int getNumApplications() { - int count = 0; - for (UiccCardApplication a : mUiccApplications) { - if (a != null) { - count++; - } + synchronized (mLock) { + return mApplicationCount; } - return count; } /** diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/RuimRecordsTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/RuimRecordsTest.java new file mode 100644 index 0000000000..b86725edd7 --- /dev/null +++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/RuimRecordsTest.java @@ -0,0 +1,88 @@ +/* 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); + } +} -- GitLab From cf61807cec157d903544629ed36b939b1dcbb825 Mon Sep 17 00:00:00 2001 From: Avinash Nalluri Date: Sat, 5 Oct 2019 14:29:30 -0700 Subject: [PATCH 3/3] Split uicc records loading in two groups. Add the apis related to split of UICC records in two groups. The first group constitutes records knowns as essential records. Basically, essential from the data call establishment perspective. Remaining records are moved to second group. Records reading is sequential so essential records are read prior to other records. Also introduced registrant apis to get notified when these few essential records are read. SIM, RUIM and ISIM identified different set of records as essential. The current grouping is based on heuristic and can be tuned in future based on field trials. Change-Id: Ic8fa54b33f97365999bd19dcfcfed319bc88a0ab CRs-Fixed: 2568904 --- .../telephony/dataconnection/DcTracker.java | 17 +++-- .../internal/telephony/uicc/IccRecords.java | 42 +++++++++++ .../telephony/uicc/IsimUiccRecords.java | 23 +++++- .../internal/telephony/uicc/RuimRecords.java | 60 +++++++++++---- .../internal/telephony/uicc/SIMRecords.java | 75 +++++++++++++------ 5 files changed, 170 insertions(+), 47 deletions(-) diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java index 9ff06b5013..4e45a928d9 100644 --- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java +++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java @@ -253,7 +253,7 @@ public class DcTracker extends Handler { // Default sent packets without ack which triggers initial recovery steps private static final int NUMBER_SENT_PACKETS_OF_HANG = 10; - private static final int EVENT_SIM_RECORDS_LOADED = 100; + private static final int EVENT_ESSENTIAL_SIM_RECORDS_LOADED = 100; // Default for the data stall alarm while non-aggressive stall detection private static final int DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS_DEFAULT = 1000 * 60 * 6; @@ -1367,7 +1367,8 @@ public class DcTracker extends Handler { radioStateFromCarrier = true; } - boolean recordsLoaded = mIccRecords.get() != null && mIccRecords.get().getRecordsLoaded(); + boolean recordsLoaded = mIccRecords.get() != null + && mIccRecords.get().getEssentialRecordsLoaded(); boolean defaultDataSelected = SubscriptionManager.isValidSubscriptionId( SubscriptionManager.getDefaultDataSubscriptionId()); @@ -3562,7 +3563,7 @@ public class DcTracker extends Handler { if (mSubscriptionManager.isActiveSubId(subId)) { onRecordsLoadedOrSubIdChanged(); } else { - log("Ignoring EVENT_RECORDS_LOADED as subId is not valid: " + subId); + log("Ignoring EVENT_ESSENTIAL_SIM_RECORDS_LOADED as subId is not valid: " + subId); } } @@ -3579,16 +3580,18 @@ public class DcTracker extends Handler { case DctConstants.EVENT_RECORDS_LOADED: mSimRecords = mPhone.getSIMRecords(); if ((mIccRecords.get() instanceof RuimRecords) && (mSimRecords != null)) { - mSimRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null); + mSimRecords.registerForEssentialRecordsLoaded( + this, EVENT_ESSENTIAL_SIM_RECORDS_LOADED, null); } else { onRecordsLoaded(); } break; - case EVENT_SIM_RECORDS_LOADED: + case EVENT_ESSENTIAL_SIM_RECORDS_LOADED: + if (DBG) log("EVENT_ESSENTIAL_SIM_RECORDS_LOADED"); onRecordsLoaded(); if (mSimRecords != null) { - mSimRecords.unregisterForRecordsLoaded(this); + mSimRecords.unregisterForEssentialRecordsLoaded(this); mSimRecords = null; } break; @@ -4005,7 +4008,7 @@ public class DcTracker extends Handler { if (mSubscriptionManager.isActiveSubId(mPhone.getSubId())) { log("New records found."); mIccRecords.set(newIccRecords); - newIccRecords.registerForRecordsLoaded( + newIccRecords.registerForEssentialRecordsLoaded( this, DctConstants.EVENT_RECORDS_LOADED, null); } } else { diff --git a/src/java/com/android/internal/telephony/uicc/IccRecords.java b/src/java/com/android/internal/telephony/uicc/IccRecords.java index 7944f6f4d1..7d432aef0b 100644 --- a/src/java/com/android/internal/telephony/uicc/IccRecords.java +++ b/src/java/com/android/internal/telephony/uicc/IccRecords.java @@ -92,6 +92,7 @@ public abstract class IccRecords extends Handler implements IccConstants { protected TelephonyManager mTelephonyManager; protected RegistrantList mRecordsLoadedRegistrants = new RegistrantList(); + protected RegistrantList mEssentialRecordsLoadedRegistrants = new RegistrantList(); protected RegistrantList mLockedRecordsLoadedRegistrants = new RegistrantList(); protected RegistrantList mNetworkLockedRecordsLoadedRegistrants = new RegistrantList(); protected RegistrantList mImsiReadyRegistrants = new RegistrantList(); @@ -102,6 +103,12 @@ public abstract class IccRecords extends Handler implements IccConstants { protected RegistrantList mSpnUpdatedRegistrants = new RegistrantList(); protected RegistrantList mRecordsOverrideRegistrants = new RegistrantList(); + @UnsupportedAppUsage + protected boolean mEssentialRecordsListenerNotified; + + @UnsupportedAppUsage + protected int mEssentialRecordsToLoad; // number of pending essential records load requests + @UnsupportedAppUsage protected int mRecordsToLoad; // number of pending load requests @@ -232,6 +239,7 @@ public abstract class IccRecords extends Handler implements IccConstants { + " mCi=" + mCi + " mFh=" + mFh + " mParentApp=" + mParentApp + + " mEssentialRecordsToLoad=" + mEssentialRecordsToLoad + " recordsToLoad=" + mRecordsToLoad + " adnCache=" + mAdnCache + " recordsRequested=" + mRecordsRequested @@ -370,6 +378,20 @@ public abstract class IccRecords extends Handler implements IccConstants { return mFullIccId; } + @UnsupportedAppUsage + public void registerForEssentialRecordsLoaded(Handler h, int what, Object obj) { + if (mDestroyed.get()) { + return; + } + + Registrant r = new Registrant(h, what, obj); + mEssentialRecordsLoadedRegistrants.add(r); + + if (getEssentialRecordsLoaded()) { + r.notifyRegistrant(new AsyncResult(null, null, null)); + } + } + @UnsupportedAppUsage public void registerForRecordsLoaded(Handler h, int what, Object obj) { if (mDestroyed.get()) { @@ -383,6 +405,12 @@ public abstract class IccRecords extends Handler implements IccConstants { r.notifyRegistrant(new AsyncResult(null, null, null)); } } + + @UnsupportedAppUsage + public void unregisterForEssentialRecordsLoaded(Handler h) { + mEssentialRecordsLoadedRegistrants.remove(h); + } + @UnsupportedAppUsage public void unregisterForRecordsLoaded(Handler h) { mRecordsLoadedRegistrants.remove(h); @@ -771,6 +799,11 @@ public abstract class IccRecords extends Handler implements IccConstants { */ public abstract void onRefresh(boolean fileChanged, int[] fileList); + @UnsupportedAppUsage + public boolean getEssentialRecordsLoaded() { + return mEssentialRecordsToLoad == 0 && mRecordsRequested; + } + @UnsupportedAppUsage public boolean getRecordsLoaded() { return mRecordsToLoad == 0 && mRecordsRequested; @@ -919,6 +952,8 @@ public abstract class IccRecords extends Handler implements IccConstants { protected abstract void onRecordLoaded(); + protected abstract void onAllEssentialRecordsLoaded(); + protected abstract void onAllRecordsLoaded(); /** @@ -1187,6 +1222,12 @@ public abstract class IccRecords extends Handler implements IccConstants { pw.println(" mCi=" + mCi); pw.println(" mFh=" + mFh); pw.println(" mParentApp=" + mParentApp); + pw.println(" mEssentialRecordsLoadedRegistrants: size=" + + mEssentialRecordsLoadedRegistrants.size()); + for (int i = 0; i < mEssentialRecordsLoadedRegistrants.size(); i++) { + pw.println(" mEssentialRecordsLoadedRegistrants[" + i + "]=" + + ((Registrant)mEssentialRecordsLoadedRegistrants.get(i)).getHandler()); + } pw.println(" recordsLoadedRegistrants: size=" + mRecordsLoadedRegistrants.size()); for (int i = 0; i < mRecordsLoadedRegistrants.size(); i++) { pw.println(" recordsLoadedRegistrants[" + i + "]=" @@ -1227,6 +1268,7 @@ public abstract class IccRecords extends Handler implements IccConstants { } pw.println(" mRecordsRequested=" + mRecordsRequested); pw.println(" mLockedRecordsReqReason=" + mLockedRecordsReqReason); + pw.println(" mEssentialRecordsToLoad=" + mEssentialRecordsToLoad); pw.println(" mRecordsToLoad=" + mRecordsToLoad); pw.println(" mRdnCache=" + mAdnCache); diff --git a/src/java/com/android/internal/telephony/uicc/IsimUiccRecords.java b/src/java/com/android/internal/telephony/uicc/IsimUiccRecords.java index f75849dcc3..b5b7b45e2e 100644 --- a/src/java/com/android/internal/telephony/uicc/IsimUiccRecords.java +++ b/src/java/com/android/internal/telephony/uicc/IsimUiccRecords.java @@ -154,9 +154,16 @@ public class IsimUiccRecords extends IccRecords implements IsimRecords { } } + private void fetchEssentialIsimRecords() { + //NOP: No essential ISim records identified. + } + @UnsupportedAppUsage protected void fetchIsimRecords() { mRecordsRequested = true; + if (DBG) log("fetchIsimRecords " + mRecordsToLoad); + + fetchEssentialIsimRecords(); mFh.loadEFTransparent(EF_IMPI, obtainMessage( IccRecords.EVENT_GET_ICC_RECORD_DONE, new EfIsimImpiLoaded())); @@ -289,13 +296,18 @@ public class IsimUiccRecords extends IccRecords implements IsimRecords { mRecordsToLoad -= 1; if (DBG) log("onRecordLoaded " + mRecordsToLoad + " requested: " + mRecordsRequested); + if (getEssentialRecordsLoaded() && !mEssentialRecordsListenerNotified) { + onAllEssentialRecordsLoaded(); + } + if (getRecordsLoaded()) { onAllRecordsLoaded(); } else if (getLockedRecordsLoaded() || getNetworkLockedRecordsLoaded()) { onLockedAllRecordsLoaded(); - } else if (mRecordsToLoad < 0) { + } else if (mRecordsToLoad < 0 || mEssentialRecordsToLoad < 0) { loge("recordsToLoad <0, programmer error suspected"); mRecordsToLoad = 0; + mEssentialRecordsToLoad = 0; } } @@ -312,9 +324,16 @@ public class IsimUiccRecords extends IccRecords implements IsimRecords { } } + @Override + protected void onAllEssentialRecordsLoaded() { + if (DBG) log("Essential record load complete"); + mEssentialRecordsListenerNotified = true; + mEssentialRecordsLoadedRegistrants.notifyRegistrants(new AsyncResult(null, null, null)); + } + @Override protected void onAllRecordsLoaded() { - if (DBG) log("record load complete"); + if (DBG) log("record load complete"); mLoaded.set(true); mRecordsLoadedRegistrants.notifyRegistrants(new AsyncResult(null, null, null)); } diff --git a/src/java/com/android/internal/telephony/uicc/RuimRecords.java b/src/java/com/android/internal/telephony/uicc/RuimRecords.java index 832349438a..c69d7f4d8a 100644 --- a/src/java/com/android/internal/telephony/uicc/RuimRecords.java +++ b/src/java/com/android/internal/telephony/uicc/RuimRecords.java @@ -376,6 +376,7 @@ public class RuimRecords extends IccRecords { @Override public void onRecordLoaded(AsyncResult ar) { + mEssentialRecordsToLoad -= 1; byte[] data = (byte[]) ar.result; if (data == null || data.length < 10) { if (DBG) log("Invalid IMSI from EF_CSIM_IMSIM"); @@ -664,6 +665,7 @@ public class RuimRecords extends IccRecords { /* IO events */ case EVENT_GET_IMSI_DONE: isRecordLoadResponse = true; + mEssentialRecordsToLoad -= 1; ar = (AsyncResult)msg.obj; if (ar.exception != null) { @@ -715,6 +717,7 @@ public class RuimRecords extends IccRecords { case EVENT_GET_ICCID_DONE: isRecordLoadResponse = true; + mEssentialRecordsToLoad -= 1; ar = (AsyncResult)msg.obj; data = (byte[])ar.result; @@ -793,13 +796,18 @@ public class RuimRecords extends IccRecords { mRecordsToLoad -= 1; if (DBG) log("onRecordLoaded " + mRecordsToLoad + " requested: " + mRecordsRequested); + if (getEssentialRecordsLoaded() && !mEssentialRecordsListenerNotified) { + onAllEssentialRecordsLoaded(); + } + if (getRecordsLoaded()) { onAllRecordsLoaded(); } else if (getLockedRecordsLoaded() || getNetworkLockedRecordsLoaded()) { onLockedAllRecordsLoaded(); - } else if (mRecordsToLoad < 0) { + } else if (mRecordsToLoad < 0 || mEssentialRecordsToLoad < 0) { loge("recordsToLoad <0, programmer error suspected"); mRecordsToLoad = 0; + mEssentialRecordsToLoad = 0; } } @@ -816,8 +824,8 @@ public class RuimRecords extends IccRecords { } @Override - protected void onAllRecordsLoaded() { - if (DBG) log("record load complete"); + protected void onAllEssentialRecordsLoaded() { + if (DBG) log("Essential record load complete"); // Further records that can be inserted are Operator/OEM dependent @@ -825,26 +833,34 @@ public class RuimRecords extends IccRecords { if (false) { String operator = getRUIMOperatorNumeric(); if (!TextUtils.isEmpty(operator)) { - log("onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" + + log("onAllEssentialRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" + operator + "'"); log("update icc_operator_numeric=" + operator); mTelephonyManager.setSimOperatorNumericForPhone( mParentApp.getPhoneId(), operator); } else { - log("onAllRecordsLoaded empty 'gsm.sim.operator.numeric' skipping"); + log("onAllEssentialRecordsLoaded empty 'gsm.sim.operator.numeric' skipping"); } String imsi = getIMSI(); if (!TextUtils.isEmpty(imsi)) { - log("onAllRecordsLoaded set mcc imsi=" + (VDBG ? ("=" + imsi) : "")); + log("onAllEssentialRecordsLoaded set mcc imsi=" + (VDBG ? ("=" + imsi) : "")); mTelephonyManager.setSimCountryIsoForPhone(mParentApp.getPhoneId(), MccTable.countryCodeForMcc(imsi.substring(0, 3))); } else { - log("onAllRecordsLoaded empty imsi skipping setting mcc"); + log("onAllEssentialRecordsLoaded empty imsi skipping setting mcc"); } } + mEssentialRecordsListenerNotified = true; + mEssentialRecordsLoadedRegistrants.notifyRegistrants(new AsyncResult(null, null, null)); + } + + @Override + protected void onAllRecordsLoaded() { + if (DBG) log("record load complete"); + Resources resource = Resources.getSystem(); if (resource.getBoolean(com.android.internal.R.bool.config_use_sim_language_file)) { setSimLanguage(mEFli, mEFpl); @@ -881,21 +897,37 @@ public class RuimRecords extends IccRecords { mRecordsToLoad++; } - @UnsupportedAppUsage - private void fetchRuimRecords() { - mRecordsRequested = true; - - if (DBG) log("fetchRuimRecords " + mRecordsToLoad); + private void fetchEssentialRuimRecords() { + if (DBG) log("fetchEssentialRuimRecords " + mRecordsToLoad); if (!TextUtils.isEmpty(mParentApp.getAid()) || mParentApp.getUiccProfile().getNumApplications() <= 1) { mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE)); mRecordsToLoad++; + mEssentialRecordsToLoad++; } mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE)); mRecordsToLoad++; + mEssentialRecordsToLoad++; + + mFh.loadEFTransparent(EF_CSIM_IMSIM, + obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimImsimLoaded())); + mRecordsToLoad++; + mEssentialRecordsToLoad++; + + if (DBG) log("fetchEssentialRuimRecords " + mRecordsToLoad + + " requested: " + mRecordsRequested); + } + + @UnsupportedAppUsage + private void fetchRuimRecords() { + mRecordsRequested = true; + + fetchEssentialRuimRecords(); + + if (DBG) log("fetchRuimRecords " + mRecordsToLoad); mFh.loadEFTransparent(EF_PL, obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfPlLoaded())); @@ -913,10 +945,6 @@ public class RuimRecords extends IccRecords { obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimMdnLoaded())); mRecordsToLoad++; - mFh.loadEFTransparent(EF_CSIM_IMSIM, - obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimImsimLoaded())); - mRecordsToLoad++; - mFh.loadEFLinearFixedAll(EF_CSIM_CDMAHOME, obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimCdmaHomeLoaded())); mRecordsToLoad++; diff --git a/src/java/com/android/internal/telephony/uicc/SIMRecords.java b/src/java/com/android/internal/telephony/uicc/SIMRecords.java index 4f5f37068e..a157709555 100755 --- a/src/java/com/android/internal/telephony/uicc/SIMRecords.java +++ b/src/java/com/android/internal/telephony/uicc/SIMRecords.java @@ -639,6 +639,7 @@ public class SIMRecords extends IccRecords { /* IO events */ case EVENT_GET_IMSI_DONE: isRecordLoadResponse = true; + mEssentialRecordsToLoad -= 1; ar = (AsyncResult) msg.obj; if (ar.exception != null) { @@ -745,6 +746,7 @@ public class SIMRecords extends IccRecords { case EVENT_GET_MSISDN_DONE: isRecordLoadResponse = true; + mEssentialRecordsToLoad -= 1; ar = (AsyncResult) msg.obj; @@ -819,6 +821,7 @@ public class SIMRecords extends IccRecords { case EVENT_GET_ICCID_DONE: isRecordLoadResponse = true; + mEssentialRecordsToLoad -= 1; ar = (AsyncResult) msg.obj; data = (byte[]) ar.result; @@ -1111,6 +1114,7 @@ public class SIMRecords extends IccRecords { case EVENT_GET_GID1_DONE: isRecordLoadResponse = true; + mEssentialRecordsToLoad -= 1; ar = (AsyncResult) msg.obj; data = (byte[]) ar.result; @@ -1129,6 +1133,7 @@ public class SIMRecords extends IccRecords { case EVENT_GET_GID2_DONE: isRecordLoadResponse = true; + mEssentialRecordsToLoad -= 1; ar = (AsyncResult) msg.obj; data = (byte[]) ar.result; @@ -1380,13 +1385,18 @@ public class SIMRecords extends IccRecords { mRecordsToLoad -= 1; if (DBG) log("onRecordLoaded " + mRecordsToLoad + " requested: " + mRecordsRequested); + if (getEssentialRecordsLoaded() && !mEssentialRecordsListenerNotified) { + onAllEssentialRecordsLoaded(); + } + if (getRecordsLoaded()) { onAllRecordsLoaded(); } else if (getLockedRecordsLoaded() || getNetworkLockedRecordsLoaded()) { onLockedAllRecordsLoaded(); - } else if (mRecordsToLoad < 0) { + }else if (mRecordsToLoad < 0 || mEssentialRecordsToLoad < 0) { loge("recordsToLoad <0, programmer error suspected"); mRecordsToLoad = 0; + mEssentialRecordsToLoad = 0; } } @@ -1430,35 +1440,41 @@ public class SIMRecords extends IccRecords { } @Override - protected void onAllRecordsLoaded() { - if (DBG) log("record load complete"); - - setSimLanguageFromEF(); - setVoiceCallForwardingFlagFromSimRecords(); - - // Some fields require more than one SIM record to set + protected void onAllEssentialRecordsLoaded() { + if (DBG) log("Essential record load complete"); String operator = getOperatorNumeric(); if (!TextUtils.isEmpty(operator)) { - log("onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" + + log("onAllEssentialRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" + operator + "'"); mTelephonyManager.setSimOperatorNumericForPhone( mParentApp.getPhoneId(), operator); } else { - log("onAllRecordsLoaded empty 'gsm.sim.operator.numeric' skipping"); + log("onAllEssentialRecordsLoaded empty 'gsm.sim.operator.numeric' skipping"); } String imsi = getIMSI(); if (!TextUtils.isEmpty(imsi) && imsi.length() >= 3) { - log("onAllRecordsLoaded set mcc imsi" + (VDBG ? ("=" + imsi) : "")); + log("onEssentialAllRecordsLoaded set mcc imsi" + (VDBG ? ("=" + imsi) : "")); mTelephonyManager.setSimCountryIsoForPhone( mParentApp.getPhoneId(), MccTable.countryCodeForMcc(imsi.substring(0, 3))); } else { - log("onAllRecordsLoaded empty imsi skipping setting mcc"); + log("onEssentialAllRecordsLoaded empty imsi skipping setting mcc"); } setVoiceMailByCountry(operator); + mEssentialRecordsListenerNotified = true; + mEssentialRecordsLoadedRegistrants.notifyRegistrants(new AsyncResult(null, null, null)); + } + + @Override + protected void onAllRecordsLoaded() { + if (DBG) log("record load complete"); + + setSimLanguageFromEF(); + setVoiceCallForwardingFlagFromSimRecords(); + mLoaded.set(true); mRecordsLoadedRegistrants.notifyRegistrants(new AsyncResult(null, null, null)); } @@ -1519,23 +1535,43 @@ public class SIMRecords extends IccRecords { mRecordsToLoad++; } - @UnsupportedAppUsage - protected void fetchSimRecords() { - mRecordsRequested = true; - - if (DBG) log("fetchSimRecords " + mRecordsToLoad); + private void fetchEssentialSimRecords() { + if (DBG) log("fetchEssentialSimRecords " + mRecordsToLoad); mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE)); mRecordsToLoad++; + mEssentialRecordsToLoad++; mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE)); mRecordsToLoad++; + mEssentialRecordsToLoad++; // FIXME should examine EF[MSISDN]'s capability configuration // to determine which is the voice/data/fax line new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN, getExtFromEf(EF_MSISDN), 1, obtainMessage(EVENT_GET_MSISDN_DONE)); mRecordsToLoad++; + mEssentialRecordsToLoad++; + + mFh.loadEFTransparent(EF_GID1, obtainMessage(EVENT_GET_GID1_DONE)); + mRecordsToLoad++; + mEssentialRecordsToLoad++; + + mFh.loadEFTransparent(EF_GID2, obtainMessage(EVENT_GET_GID2_DONE)); + mRecordsToLoad++; + mEssentialRecordsToLoad++; + + if (DBG) log("fetchEssentialSimRecords " + mRecordsToLoad + + " requested: " + mRecordsRequested); + } + + @UnsupportedAppUsage + protected void fetchSimRecords() { + mRecordsRequested = true; + + fetchEssentialSimRecords(); + + if (DBG) log("fetchSimRecords " + mRecordsToLoad); // Record number is subscriber profile mFh.loadEFLinearFixed(EF_MBI, 1, obtainMessage(EVENT_GET_MBI_DONE)); @@ -1579,11 +1615,6 @@ public class SIMRecords extends IccRecords { mFh.loadEFTransparent(EF_CSP_CPHS,obtainMessage(EVENT_GET_CSP_CPHS_DONE)); mRecordsToLoad++; - mFh.loadEFTransparent(EF_GID1, obtainMessage(EVENT_GET_GID1_DONE)); - mRecordsToLoad++; - - mFh.loadEFTransparent(EF_GID2, obtainMessage(EVENT_GET_GID2_DONE)); - mRecordsToLoad++; mFh.loadEFTransparent(EF_PLMN_W_ACT, obtainMessage(EVENT_GET_PLMN_W_ACT_DONE)); mRecordsToLoad++; -- GitLab