From c46a085eedef8c7c59df4b182d90d787f1ff0f04 Mon Sep 17 00:00:00 2001 From: Kazuhiro Ondo Date: Tue, 24 May 2011 00:08:09 -0500 Subject: [PATCH] Read CSIM records in LTE on CDMA mode In case of CDMA and LTE hybrid system, UICC card contains both USIM and CSIM data. FW needs to read out from both to aqcuire information required for the service. Change-Id: I4a714252bc97c037fa419352f23d8f38f6206406 --- .../internal/telephony/IccConstants.java | 6 + .../internal/telephony/IccFileHandler.java | 1 + .../internal/telephony/cdma/CDMALTEPhone.java | 3 +- .../internal/telephony/cdma/CDMAPhone.java | 2 +- .../cdma/CdmaLteUiccFileHandler.java | 52 +++++ .../telephony/cdma/CdmaLteUiccRecords.java | 215 ++++++++++++++++++ .../internal/telephony/gsm/SIMRecords.java | 16 +- 7 files changed, 286 insertions(+), 9 deletions(-) create mode 100644 telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java create mode 100755 telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java diff --git a/telephony/java/com/android/internal/telephony/IccConstants.java b/telephony/java/com/android/internal/telephony/IccConstants.java index b40f945d6c68c..cafc79bf5fd9a 100644 --- a/telephony/java/com/android/internal/telephony/IccConstants.java +++ b/telephony/java/com/android/internal/telephony/IccConstants.java @@ -58,6 +58,12 @@ public interface IccConstants { static final int EF_CST = 0x6f32; static final int EF_RUIM_SPN =0x6F41; + // ETSI TS.102.221 + static final int EF_PL = 0x2F05; + // 3GPP2 C.S0065 + static final int EF_CSIM_LI = 0x6F3A; + static final int EF_CSIM_SPN =0x6F41; + //ISIM access static final int EF_IMPU = 0x6f04; static final int EF_IMPI = 0x6f02; diff --git a/telephony/java/com/android/internal/telephony/IccFileHandler.java b/telephony/java/com/android/internal/telephony/IccFileHandler.java index 92ddd2c2cb45b..93b9b792a89b2 100644 --- a/telephony/java/com/android/internal/telephony/IccFileHandler.java +++ b/telephony/java/com/android/internal/telephony/IccFileHandler.java @@ -529,6 +529,7 @@ public abstract class IccFileHandler extends Handler implements IccConstants { return MF_SIM + DF_TELECOM; case EF_ICCID: + case EF_PL: return MF_SIM; case EF_IMG: return MF_SIM + DF_TELECOM + DF_GRAPHICS; diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java index 5733164c1445e..fe2fcb22db245 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java @@ -58,8 +58,9 @@ public class CDMALTEPhone extends CDMAPhone { @Override protected void initSstIcc() { mSST = new CdmaLteServiceStateTracker(this); - mIccRecords = new SIMRecords(this); + mIccRecords = new CdmaLteUiccRecords(this); mIccCard = new SimCard(this, LOG_TAG, DBG); + mIccFileHandler = new CdmaLteUiccFileHandler(this); } @Override diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java index c85f7d860bb31..a283062cc674c 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java @@ -156,13 +156,13 @@ public class CDMAPhone extends PhoneBase { mSST = new CdmaServiceStateTracker(this); mIccRecords = new RuimRecords(this); mIccCard = new RuimCard(this, LOG_TAG, DBG); + mIccFileHandler = new RuimFileHandler(this); } protected void init(Context context, PhoneNotifier notifier) { mCM.setPhoneType(Phone.PHONE_TYPE_CDMA); mCT = new CdmaCallTracker(this); mSMS = new CdmaSMSDispatcher(this); - mIccFileHandler = new RuimFileHandler(this); mDataConnectionTracker = new CdmaDataConnectionTracker (this); mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this); mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this, mSMS); diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java new file mode 100644 index 0000000000000..2aede29e01e04 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011 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.cdma; + +import android.util.Log; +import com.android.internal.telephony.IccConstants; +import com.android.internal.telephony.IccFileHandler; + +/** + * {@hide} + */ +public final class CdmaLteUiccFileHandler extends IccFileHandler { + static final String LOG_TAG = "CDMA"; + + CdmaLteUiccFileHandler(CDMALTEPhone phone) { + super(phone); + } + + protected String getEFPath(int efid) { + switch(efid) { + case EF_CSIM_SPN: + case EF_CSIM_LI: + return MF_SIM + DF_CDMA; + case EF_AD: + return MF_SIM + DF_GSM; + } + return getCommonIccEFPath(efid); + } + + protected void logd(String msg) { + Log.d(LOG_TAG, "[CdmaLteUiccFileHandler] " + msg); + } + + protected void loge(String msg) { + Log.e(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 new file mode 100755 index 0000000000000..78879d690cd1f --- /dev/null +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2011 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.cdma; + +import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA; +import com.android.internal.telephony.GsmAlphabet; +import com.android.internal.telephony.IccFileHandler; +import com.android.internal.telephony.IccUtils; +import com.android.internal.telephony.PhoneBase; +import com.android.internal.telephony.cdma.sms.UserData; +import com.android.internal.telephony.gsm.SIMRecords; +import android.os.AsyncResult; +import android.os.Message; +import android.os.SystemProperties; +import android.util.Log; + + +/** + * {@hide} + */ +public final class CdmaLteUiccRecords extends SIMRecords { + // From CSIM application + private byte[] mEFpl = null; + private byte[] mEFli = null; + boolean csimSpnDisplayCondition = false; + + 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; + + public CdmaLteUiccRecords(PhoneBase p) { + super(p); + } + + @Override + public void handleMessage(Message msg) { + AsyncResult ar; + byte data[]; + + boolean isCsimRecordLoadResponse = false; + + try { switch (msg.what) { + case EVENT_GET_PL_DONE: + // Refer to ETSI TS.102.221 + if (DBG) log("EF_GET_EF_PL_DONE"); + isCsimRecordLoadResponse = true; + + ar = (AsyncResult) msg.obj; + + if (ar.exception != null) { + Log.e(LOG_TAG, "ar.exception = " + ar.exception); + break; + } + + mEFpl = (byte[]) ar.result; + if (DBG) log("EF_PL=" + IccUtils.bytesToHexString(mEFpl)); + break; + + case EVENT_GET_CSIM_LI_DONE: + // Refer to C.S0065 5.2.26 + if (DBG) log("EVENT_GET_CSIM_LI_DONE"); + isCsimRecordLoadResponse = true; + + ar = (AsyncResult) msg.obj; + if (ar.exception != null) { + Log.e(LOG_TAG, "ar.exception = " + ar.exception); + break; + } + + mEFli = (byte[]) ar.result; + // convert csim efli data to iso 639 format + for (int i = 0; i < mEFli.length; i+=2) { + switch(mEFli[i+1]) { + case 0x01: mEFli[i] = 'e'; mEFli[i+1] = 'n';break; + case 0x02: mEFli[i] = 'f'; mEFli[i+1] = 'r';break; + case 0x03: mEFli[i] = 'e'; mEFli[i+1] = 's';break; + case 0x04: mEFli[i] = 'j'; mEFli[i+1] = 'a';break; + case 0x05: mEFli[i] = 'k'; mEFli[i+1] = 'o';break; + case 0x06: mEFli[i] = 'z'; mEFli[i+1] = 'h';break; + case 0x07: mEFli[i] = 'h'; mEFli[i+1] = 'e';break; + default: mEFli[i] = ' '; mEFli[i+1] = ' '; + } + } + + if (DBG) log("EF_LI=" + IccUtils.bytesToHexString(mEFli)); + break; + case EVENT_GET_CSIM_SPN_DONE: + // Refer to C.S0065 5.2.32 + if (DBG) log("EVENT_GET_CSIM_SPN_DONE"); + isCsimRecordLoadResponse = true; + ar = (AsyncResult) msg.obj; + + if (ar.exception != null) { + Log.e(LOG_TAG, "ar.exception=" + ar.exception); + break; + } + onGetCSimSpnDone(ar); + break; + default: + super.handleMessage(msg); + }}catch (RuntimeException exc) { + Log.w(LOG_TAG, "Exception parsing SIM record", exc); + } finally { + if (isCsimRecordLoadResponse) { + onRecordLoaded(); + } + } + } + + @Override + protected void onRecordLoaded() { + // One record loaded successfully or failed, In either case + // we need to update the recordsToLoad count + recordsToLoad -= 1; + + if (recordsToLoad == 0 && recordsRequested == true) { + onAllRecordsLoaded(); + } else if (recordsToLoad < 0) { + Log.e(LOG_TAG, "SIMRecords: recordsToLoad <0, programmer error suspected"); + recordsToLoad = 0; + } + } + + @Override + protected void fetchSimRecords() { + IccFileHandler iccFh = phone.getIccFileHandler(); + recordsRequested = true; + + phone.mCM.getIMSI(obtainMessage(EVENT_GET_IMSI_DONE)); + recordsToLoad++; + + iccFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE)); + recordsToLoad++; + + iccFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE)); + recordsToLoad++; + + iccFh.loadEFTransparent(EF_PL, obtainMessage(EVENT_GET_PL_DONE)); + recordsToLoad++; + + iccFh.loadEFTransparent(EF_CSIM_LI, obtainMessage(EVENT_GET_CSIM_LI_DONE)); + recordsToLoad++; + + iccFh.loadEFTransparent(EF_CSIM_SPN, obtainMessage(EVENT_GET_CSIM_SPN_DONE)); + recordsToLoad++; + } + + private void onGetCSimSpnDone(AsyncResult ar) { + byte[] data = (byte[]) ar.result; + if (DBG) log("CSIM_SPN=" + + IccUtils.bytesToHexString(data)); + + // C.S0065 for EF_SPN decoding + csimSpnDisplayCondition = ((0x02 & data[0]) > 0)?true:false; + + int encoding = data[1]; + int language = data[2]; + byte[] spnData = new byte[32]; + System.arraycopy(data, 3, spnData, 0, (data.length < 32)?data.length:32); + + int numBytes; + for (numBytes = 0; numBytes < spnData.length; numBytes++) { + if ((spnData[numBytes] & 0xFF) == 0xFF) break; + } + + if (numBytes == 0) { + spn = ""; + return; + } + try { + switch (encoding) { + case UserData.ENCODING_OCTET: + case UserData.ENCODING_LATIN: + spn = new String(spnData, 0, numBytes, "ISO-8859-1"); + break; + case UserData.ENCODING_IA5: + case UserData.ENCODING_GSM_7BIT_ALPHABET: + case UserData.ENCODING_7BIT_ASCII: + spn = GsmAlphabet.gsm7BitPackedToString(spnData, 0, (numBytes*8)/7); + break; + case UserData.ENCODING_UNICODE_16: + spn = new String(spnData, 0, numBytes, "utf-16"); + break; + default: + log("SPN encoding not supported"); + } + } catch(Exception e) { + log("spn decode error: " + e); + } + if (DBG) log("spn=" + spn); + if (DBG) log("spnCondition=" + csimSpnDisplayCondition); + phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, spn); + } + + public byte[] getPreferredLanguage() { + return mEFpl; + } + + public byte[] getLanguageIndication() { + return mEFli; + } +} diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java index 4cd9440d23e68..b0bad56a4a79c 100755 --- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java +++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java @@ -45,12 +45,12 @@ import java.util.ArrayList; /** * {@hide} */ -public final class SIMRecords extends IccRecords { - static final String LOG_TAG = "GSM"; +public class SIMRecords extends IccRecords { + protected static final String LOG_TAG = "GSM"; private static final boolean CRASH_RIL = false; - private static final boolean DBG = true; + protected static final boolean DBG = true; // ***** Instance Variables @@ -120,13 +120,13 @@ public final class SIMRecords extends IccRecords { private static final int EVENT_SIM_READY = 1; private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 2; - private static final int EVENT_GET_IMSI_DONE = 3; - private static final int EVENT_GET_ICCID_DONE = 4; + protected static final int EVENT_GET_IMSI_DONE = 3; + protected static final int EVENT_GET_ICCID_DONE = 4; private static final int EVENT_GET_MBI_DONE = 5; private static final int EVENT_GET_MBDN_DONE = 6; private static final int EVENT_GET_MWIS_DONE = 7; private static final int EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE = 8; - private static final int EVENT_GET_AD_DONE = 9; // Admin data on SIM + protected static final int EVENT_GET_AD_DONE = 9; // Admin data on SIM private static final int EVENT_GET_MSISDN_DONE = 10; private static final int EVENT_GET_CPHS_MAILBOX_DONE = 11; private static final int EVENT_GET_SPN_DONE = 12; @@ -147,6 +147,8 @@ public final class SIMRecords extends IccRecords { private static final int EVENT_GET_CFIS_DONE = 32; private static final int EVENT_GET_CSP_CPHS_DONE = 33; + protected static final int CSIM_EVENT_BASE = 100; + // Lookup table for carriers known to produce SIMs which incorrectly indicate MNC length. private static final String[] MCCMNC_CODES_HAVING_3DIGITS_MNC = { @@ -1285,7 +1287,7 @@ public final class SIMRecords extends IccRecords { fetchSimRecords(); } - private void fetchSimRecords() { + protected void fetchSimRecords() { recordsRequested = true; IccFileHandler iccFh = phone.getIccFileHandler();