diff options
author | Wink Saville <wink@google.com> | 2011-06-08 15:03:35 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2011-06-08 15:03:35 -0700 |
commit | a384ff32827cf6383ead48ec4e0da42365ed3584 (patch) | |
tree | f9389b4851ca07eaba592f40b93ab8a5f75bbe46 | |
parent | ed17165a14e20ab5110be8c86ec1b519835613d0 (diff) | |
parent | 33e1424b2e924e9b0162aa648137e8254f729161 (diff) | |
download | frameworks_base-a384ff32827cf6383ead48ec4e0da42365ed3584.zip frameworks_base-a384ff32827cf6383ead48ec4e0da42365ed3584.tar.gz frameworks_base-a384ff32827cf6383ead48ec4e0da42365ed3584.tar.bz2 |
am 33e1424b: Merge "Use CSIM to get provision information" into honeycomb-LTE
* commit '33e1424b2e924e9b0162aa648137e8254f729161':
Use CSIM to get provision information
8 files changed, 306 insertions, 47 deletions
diff --git a/telephony/java/com/android/internal/telephony/IccConstants.java b/telephony/java/com/android/internal/telephony/IccConstants.java index cafc79b..1ba6dfe 100644 --- a/telephony/java/com/android/internal/telephony/IccConstants.java +++ b/telephony/java/com/android/internal/telephony/IccConstants.java @@ -63,6 +63,10 @@ public interface IccConstants { // 3GPP2 C.S0065 static final int EF_CSIM_LI = 0x6F3A; static final int EF_CSIM_SPN =0x6F41; + static final int EF_CSIM_MDN = 0x6F44; + static final int EF_CSIM_IMSIM = 0x6F22; + static final int EF_CSIM_CDMAHOME = 0x6F28; + static final int EF_CSIM_EPRL = 0x6F5A; //ISIM access static final int EF_IMPU = 0x6f04; diff --git a/telephony/java/com/android/internal/telephony/IccRecords.java b/telephony/java/com/android/internal/telephony/IccRecords.java index 10a3b69..3a27901 100644 --- a/telephony/java/com/android/internal/telephony/IccRecords.java +++ b/telephony/java/com/android/internal/telephony/IccRecords.java @@ -288,6 +288,16 @@ public abstract class IccRecords extends Handler implements IccConstants { } /** + * Indicates wether SIM is in provisioned state or not. + * Overridden only if SIM can be dynamically provisioned via OTA. + * + * @return true if provisioned + */ + public boolean isProvisioned () { + return true; + } + + /** * Write string to log file * * @param s is the string to write diff --git a/telephony/java/com/android/internal/telephony/IccUtils.java b/telephony/java/com/android/internal/telephony/IccUtils.java index c3b0ffc..a966f76 100644 --- a/telephony/java/com/android/internal/telephony/IccUtils.java +++ b/telephony/java/com/android/internal/telephony/IccUtils.java @@ -63,6 +63,29 @@ public class IccUtils { return ret.toString(); } + /** + * Decode cdma byte into String. + */ + public static String + cdmaBcdToString(byte[] data, int offset, int length) { + StringBuilder ret = new StringBuilder(length); + + int count = 0; + for (int i = offset; count < length; i++) { + int v; + v = data[i] & 0xf; + if (v > 9) v = 0; + ret.append((char)('0' + v)); + + if (++count == length) break; + + v = (data[i] >> 4) & 0xf; + if (v > 9) v = 0; + ret.append((char)('0' + v)); + ++count; + } + return ret.toString(); + } /** * Decodes a GSM-style BCD byte, returning an int ranging from 0-99. diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java index faae622..318cf37 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java @@ -67,11 +67,24 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker { case EVENT_SIM_READY: if (DBG) log("handleMessage EVENT_SIM_READY"); isSubscriptionFromRuim = false; - cm.getCDMASubscription( obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION)); + // Register SIM_RECORDS_LOADED dynamically. + // This is to avoid confilct with RUIM_READY scenario) + phone.mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null); pollState(); // Signal strength polling stops when radio is off. queueNextSignalStrengthPoll(); break; + case EVENT_SIM_RECORDS_LOADED: + CdmaLteUiccRecords sim = (CdmaLteUiccRecords)phone.mIccRecords; + if ((sim != null) && sim.isProvisioned()) { + mMdn = sim.getMdn(); + mMin = sim.getMin(); + parseSidNid(sim.getSid(), sim.getNid()); + mPrlVersion = sim.getPrlVersion();; + mIsMinInfoReady = true; + updateOtaspState(); + } + break; default: super.handleMessage(msg); } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java index 2aede29..b9d7c46 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java @@ -19,6 +19,7 @@ package com.android.internal.telephony.cdma; import android.util.Log; import com.android.internal.telephony.IccConstants; import com.android.internal.telephony.IccFileHandler; +import android.os.Message; /** * {@hide} @@ -34,6 +35,10 @@ public final class CdmaLteUiccFileHandler extends IccFileHandler { switch(efid) { case EF_CSIM_SPN: case EF_CSIM_LI: + case EF_CSIM_MDN: + case EF_CSIM_IMSIM: + case EF_CSIM_CDMAHOME: + case EF_CSIM_EPRL: return MF_SIM + DF_CDMA; case EF_AD: return MF_SIM + DF_GSM; @@ -41,6 +46,21 @@ public final class CdmaLteUiccFileHandler extends IccFileHandler { return getCommonIccEFPath(efid); } + @Override + public void loadEFTransparent(int fileid, Message onLoaded) { + if (fileid == EF_CSIM_EPRL) { + // Entire PRL could be huge. We are only interested in + // the first 4 bytes of the record. + phone.mCM.iccIO(COMMAND_READ_BINARY, fileid, getEFPath(fileid), + 0, 0, 4, null, null, + obtainMessage(EVENT_READ_BINARY_DONE, + fileid, 0, onLoaded)); + } else { + super.loadEFTransparent(fileid, onLoaded); + } + } + + protected void logd(String msg) { Log.d(LOG_TAG, "[CdmaLteUiccFileHandler] " + msg); } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java index 78879d6..ac77f9a 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java @@ -26,7 +26,8 @@ import android.os.AsyncResult; import android.os.Message; import android.os.SystemProperties; import android.util.Log; - +import java.util.Locale; +import java.util.ArrayList; /** * {@hide} @@ -36,10 +37,19 @@ public final class CdmaLteUiccRecords extends SIMRecords { private byte[] mEFpl = null; private byte[] mEFli = null; boolean csimSpnDisplayCondition = false; + private String mMdn; + private String mMin; + private String mPrlVersion; + private String mHomeSystemId; + private String mHomeNetworkId; private static final int EVENT_GET_PL_DONE = CSIM_EVENT_BASE; private static final int EVENT_GET_CSIM_LI_DONE = CSIM_EVENT_BASE + 1; private static final int EVENT_GET_CSIM_SPN_DONE = CSIM_EVENT_BASE + 2; + private static final int EVENT_GET_CSIM_MDN_DONE = CSIM_EVENT_BASE + 3; + private static final int EVENT_GET_CSIM_IMSIM_DONE = CSIM_EVENT_BASE + 4; + private static final int EVENT_GET_CSIM_CDMAHOME_DONE = CSIM_EVENT_BASE + 5; + private static final int EVENT_GET_CSIM_EPRL_DONE = CSIM_EVENT_BASE + 6; public CdmaLteUiccRecords(PhoneBase p) { super(p); @@ -109,6 +119,46 @@ public final class CdmaLteUiccRecords extends SIMRecords { } onGetCSimSpnDone(ar); break; + case EVENT_GET_CSIM_MDN_DONE: + if (DBG) log("EVENT_GET_CSIM_MDN_DONE"); + isCsimRecordLoadResponse = true; + ar = (AsyncResult) msg.obj; + if (ar.exception != null) { + Log.e(LOG_TAG, "ar.exception=" + ar.exception); + break; + } + onGetCSimMdnDone(ar); + break; + case EVENT_GET_CSIM_IMSIM_DONE: + if (DBG) log("EVENT_GET_CSIM_IMSIM_DONE"); + isCsimRecordLoadResponse = true; + ar = (AsyncResult) msg.obj; + if (ar.exception != null) { + Log.e(LOG_TAG, "ar.exception=" + ar.exception); + break; + } + onGetCSimImsimDone(ar); + break; + case EVENT_GET_CSIM_CDMAHOME_DONE: + if (DBG) log("EVENT_GET_CSIM_CDMAHOME_DONE"); + isCsimRecordLoadResponse = true; + ar = (AsyncResult) msg.obj; + if (ar.exception != null) { + Log.e(LOG_TAG, "ar.exception=" + ar.exception); + break; + } + onGetCSimCdmaHomeDone(ar); + break; + case EVENT_GET_CSIM_EPRL_DONE: + if (DBG) log("EVENT_GET_CSIM_EPRL_DONE"); + isCsimRecordLoadResponse = true; + ar = (AsyncResult) msg.obj; + if (ar.exception != null) { + Log.e(LOG_TAG, "ar.exception=" + ar.exception); + break; + } + onGetCSimEprlDone(ar); + break; default: super.handleMessage(msg); }}catch (RuntimeException exc) { @@ -156,6 +206,19 @@ public final class CdmaLteUiccRecords extends SIMRecords { iccFh.loadEFTransparent(EF_CSIM_SPN, obtainMessage(EVENT_GET_CSIM_SPN_DONE)); recordsToLoad++; + + iccFh.loadEFLinearFixed(EF_CSIM_MDN, 1, obtainMessage(EVENT_GET_CSIM_MDN_DONE)); + recordsToLoad++; + + iccFh.loadEFTransparent(EF_CSIM_IMSIM, obtainMessage(EVENT_GET_CSIM_IMSIM_DONE)); + recordsToLoad++; + + iccFh.loadEFLinearFixedAll(EF_CSIM_CDMAHOME, + obtainMessage(EVENT_GET_CSIM_CDMAHOME_DONE)); + recordsToLoad++; + + iccFh.loadEFTransparent(EF_CSIM_EPRL, obtainMessage(EVENT_GET_CSIM_EPRL_DONE)); + recordsToLoad++; } private void onGetCSimSpnDone(AsyncResult ar) { @@ -205,6 +268,93 @@ public final class CdmaLteUiccRecords extends SIMRecords { phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, spn); } + private void onGetCSimMdnDone(AsyncResult ar) { + byte[] data = (byte[]) ar.result; + if (DBG) log("CSIM_MDN=" + IccUtils.bytesToHexString(data)); + int mdnDigitsNum = 0x0F & data[0]; + mMdn = IccUtils.cdmaBcdToString(data, 1, mdnDigitsNum); + if (DBG) log("CSIM MDN=" + mMdn); + } + + private void onGetCSimImsimDone(AsyncResult ar) { + byte[] data = (byte[]) ar.result; + if (DBG) 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) { + 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)); + if (DBG) log("min present=" + builder.toString()); + + mMin = builder.toString(); + } else { + if (DBG) log("min not present"); + } + } + + 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; + } + + private void onGetCSimCdmaHomeDone(AsyncResult ar) { + // Per C.S0065 section 5.2.8 + ArrayList<byte[]> dataList = (ArrayList<byte[]>) ar.result; + if (DBG) log("CSIM_CDMAHOME data size=" + dataList.size()); + if (dataList.isEmpty()) { + return; + } + StringBuilder sidBuf = new StringBuilder(); + StringBuilder nidBuf = new StringBuilder(); + + for (byte[] data : dataList) { + if (data.length == 5) { + int sid = ((data[1] & 0xFF) << 8) | (data[0] & 0xFF); + int nid = ((data[3] & 0xFF) << 8) | (data[2] & 0xFF); + sidBuf.append(sid).append(","); + nidBuf.append(nid).append(","); + } + } + // remove trailing "," + sidBuf.setLength(sidBuf.length()-1); + nidBuf.setLength(nidBuf.length()-1); + + mHomeSystemId = sidBuf.toString(); + mHomeNetworkId = nidBuf.toString(); + } + + private void onGetCSimEprlDone(AsyncResult ar) { + // C.S0065 section 5.2.57 for EFeprl encoding + // C.S0016 section 3.5.5 for PRL format. + byte[] data = (byte[]) ar.result; + if (DBG) log("CSIM_EPRL=" + IccUtils.bytesToHexString(data)); + + // Only need the first 4 bytes of record + if (data.length > 3) { + int prlId = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); + mPrlVersion = Integer.toString(prlId); + } + if (DBG) log("CSIM PRL version=" + mPrlVersion); + } + public byte[] getPreferredLanguage() { return mEFpl; } @@ -212,4 +362,32 @@ public final class CdmaLteUiccRecords extends SIMRecords { public byte[] getLanguageIndication() { return mEFli; } + + public String getMdn() { + return mMdn; + } + + public String getMin() { + return mMin; + } + + public String getSid() { + return mHomeSystemId; + } + + public String getNid() { + return mHomeNetworkId; + } + + public String getPrlVersion() { + return mPrlVersion; + } + + @Override + public boolean isProvisioned() { + // Look for MDN and MIN field to determine if the SIM is provisioned. + if ((mMdn != null) && (mMin != null)) return true; + + return false; + } } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index 805ee49..5ebdd22 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -129,12 +129,12 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { /** Contains the name of the registered network in CDMA (either ONS or ERI text). */ private String curPlmn = null; - private String mMdn; + protected String mMdn; private int mHomeSystemId[] = null; private int mHomeNetworkId[] = null; - private String mMin; - private String mPrlVersion; - private boolean mIsMinInfoReady = false; + protected String mMin; + protected String mPrlVersion; + protected boolean mIsMinInfoReady = false; private boolean isEriTextLoaded = false; protected boolean isSubscriptionFromRuim = false; @@ -373,53 +373,15 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { String cdmaSubscription[] = (String[])ar.result; if (cdmaSubscription != null && cdmaSubscription.length >= 5) { mMdn = cdmaSubscription[0]; - if (cdmaSubscription[1] != null) { - String[] sid = cdmaSubscription[1].split(","); - mHomeSystemId = new int[sid.length]; - for (int i = 0; i < sid.length; i++) { - try { - mHomeSystemId[i] = Integer.parseInt(sid[i]); - } catch (NumberFormatException ex) { - loge("error parsing system id: " + ex); - } - } - } - if (DBG) log("GET_CDMA_SUBSCRIPTION: SID=" + cdmaSubscription[1] ); - - if (cdmaSubscription[2] != null) { - String[] nid = cdmaSubscription[2].split(","); - mHomeNetworkId = new int[nid.length]; - for (int i = 0; i < nid.length; i++) { - try { - mHomeNetworkId[i] = Integer.parseInt(nid[i]); - } catch (NumberFormatException ex) { - loge("GET_CDMA_SUBSCRIPTION: error parsing network id: " + ex); - } - } - } - if (DBG) log("GET_CDMA_SUBSCRIPTION: NID=" + cdmaSubscription[2]); + parseSidNid(cdmaSubscription[1], cdmaSubscription[2]); + mMin = cdmaSubscription[3]; mPrlVersion = cdmaSubscription[4]; if (DBG) log("GET_CDMA_SUBSCRIPTION: MDN=" + mMdn); mIsMinInfoReady = true; - int otaspMode = getOtasp(); - int oldOtaspMode = mCurrentOtaspMode; - mCurrentOtaspMode = otaspMode; - - // Notify apps subscription info is ready - if (cdmaForSubscriptionInfoReadyRegistrants != null) { - if (DBG) log("GET_CDMA_SUBSCRIPTION: call notifyRegistrants()"); - cdmaForSubscriptionInfoReadyRegistrants.notifyRegistrants(); - } - if (oldOtaspMode != mCurrentOtaspMode) { - if (DBG) { - log("GET_CDMA_SUBSCRIPTION: call notifyOtaspChanged old otaspMode=" + - oldOtaspMode + " new otaspMode=" + mCurrentOtaspMode); - } - phone.notifyOtaspChanged(mCurrentOtaspMode); - } + updateOtaspState(); phone.getIccCard().broadcastIccStateChangedIntent(IccCard.INTENT_VALUE_ICC_IMSI, null); } else { @@ -1622,6 +1584,53 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { cm.setRadioPower(false, null); } + protected void parseSidNid (String sidStr, String nidStr) { + if (sidStr != null) { + String[] sid = sidStr.split(","); + mHomeSystemId = new int[sid.length]; + for (int i = 0; i < sid.length; i++) { + try { + mHomeSystemId[i] = Integer.parseInt(sid[i]); + } catch (NumberFormatException ex) { + loge("error parsing system id: " + ex); + } + } + } + if (DBG) log("CDMA_SUBSCRIPTION: SID=" + sidStr); + + if (nidStr != null) { + String[] nid = nidStr.split(","); + mHomeNetworkId = new int[nid.length]; + for (int i = 0; i < nid.length; i++) { + try { + mHomeNetworkId[i] = Integer.parseInt(nid[i]); + } catch (NumberFormatException ex) { + loge("CDMA_SUBSCRIPTION: error parsing network id: " + ex); + } + } + } + if (DBG) log("CDMA_SUBSCRIPTION: NID=" + nidStr); + } + + protected void updateOtaspState() { + int otaspMode = getOtasp(); + int oldOtaspMode = mCurrentOtaspMode; + mCurrentOtaspMode = otaspMode; + + // Notify apps subscription info is ready + if (cdmaForSubscriptionInfoReadyRegistrants != null) { + if (DBG) log("CDMA_SUBSCRIPTION: call notifyRegistrants()"); + cdmaForSubscriptionInfoReadyRegistrants.notifyRegistrants(); + } + if (oldOtaspMode != mCurrentOtaspMode) { + if (DBG) { + log("CDMA_SUBSCRIPTION: call notifyOtaspChanged old otaspMode=" + + oldOtaspMode + " new otaspMode=" + mCurrentOtaspMode); + } + phone.notifyOtaspChanged(mCurrentOtaspMode); + } + } + @Override protected void log(String s) { Log.d(LOG_TAG, "[CdmaSST] " + s); diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index db2b490..dcde71a 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -561,6 +561,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { boolean allowed = (gprsState == ServiceState.STATE_IN_SERVICE || mAutoAttachOnCreation) && mPhone.mIccRecords.getRecordsLoaded() && + mPhone.mIccRecords.isProvisioned() && mPhone.getState() == Phone.State.IDLE && mInternalDataEnabled && (!mPhone.getServiceState().getRoaming() || getDataOnRoamingEnabled()) && @@ -572,6 +573,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { reason += " - gprs= " + gprsState; } if (!mPhone.mIccRecords.getRecordsLoaded()) reason += " - SIM not loaded"; + if (!mPhone.mIccRecords.isProvisioned()) reason += " - SIM not provisioned"; if (mPhone.getState() != Phone.State.IDLE) { reason += " - PhoneState= " + mPhone.getState(); } |