Merge "Use CSIM to get provision information" into honeycomb-LTE

This commit is contained in:
Wink Saville
2011-06-08 14:58:53 -07:00
committed by Android (Google) Code Review
8 changed files with 305 additions and 46 deletions

View File

@@ -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;

View File

@@ -287,6 +287,16 @@ public abstract class IccRecords extends Handler implements IccConstants {
public void setVoiceCallForwardingFlag(int line, boolean enable) {
}
/**
* 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
*

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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] );
parseSidNid(cdmaSubscription[1], cdmaSubscription[2]);
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]);
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);

View File

@@ -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();
}