diff options
Diffstat (limited to 'telephony/java/com')
20 files changed, 705 insertions, 287 deletions
diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java index b68cbe9..1caea70 100644 --- a/telephony/java/com/android/internal/telephony/CommandsInterface.java +++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java @@ -1489,11 +1489,8 @@ public interface CommandsInterface { /** * Setup a packet data connection On successful completion, the result - * message will return the following: [0] indicating PDP CID, which is - * generated by RIL. This Connection ID is used in both GSM/UMTS and CDMA - * modes [1] indicating the network interface name for GSM/UMTS or CDMA [2] - * indicating the IP address for this interface for GSM/UMTS and NULL in the - * case of CDMA + * message will return a {@link DataCallState} object containing the connection + * information. * * @param radioTechnology * indicates whether to setup connection on radio technology CDMA @@ -1569,7 +1566,7 @@ public interface CommandsInterface { /** * Request the status of the ICC and UICC cards. * - * @param response + * @param result * Callback message containing {@link IccCardStatus} structure for the card. */ public void getIccCardStatus(Message result); @@ -1583,4 +1580,14 @@ public interface CommandsInterface { * or {@link Phone#LTE_ON_CDMA_TRUE} */ public int getLteOnCdmaMode(); + + /** + * Request the ISIM application on the UICC to perform the AKA + * challenge/response algorithm for IMS authentication. The nonce string + * and challenge response are Base64 encoded Strings. + * + * @param nonce the nonce string to pass with the ISIM authentication request + * @param response a callback message with the String response in the obj field + */ + public void requestIsimAuthentication(String nonce, Message response); } diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl index 5cba2e1..def770f 100644 --- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl +++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl @@ -67,4 +67,23 @@ interface IPhoneSubInfo { * Retrieves the alpha identifier associated with the voice mail number. */ String getVoiceMailAlphaTag(); + + /** + * Returns the IMS private user identity (IMPI) that was loaded from the ISIM. + * @return the IMPI, or null if not present or not loaded + */ + String getIsimImpi(); + + /** + * Returns the IMS home network domain name that was loaded from the ISIM. + * @return the IMS domain name, or null if not present or not loaded + */ + String getIsimDomain(); + + /** + * Returns the IMS public user identities (IMPU) that were loaded from the ISIM. + * @return an array of IMPU strings, with one IMPU per string, or null if + * not present or not loaded + */ + String[] getIsimImpu(); } diff --git a/telephony/java/com/android/internal/telephony/IccRecords.java b/telephony/java/com/android/internal/telephony/IccRecords.java index 3a27901..84bfc40 100644 --- a/telephony/java/com/android/internal/telephony/IccRecords.java +++ b/telephony/java/com/android/internal/telephony/IccRecords.java @@ -22,6 +22,8 @@ import android.os.Message; import android.os.Registrant; import android.os.RegistrantList; +import com.android.internal.telephony.ims.IsimRecords; + /** * {@hide} */ @@ -70,6 +72,24 @@ public abstract class IccRecords extends Handler implements IccConstants { // ***** Event Constants protected static final int EVENT_SET_MSISDN_DONE = 30; + public static final int EVENT_GET_ICC_RECORD_DONE = 100; + + /** + * Generic ICC record loaded callback. Subclasses can call EF load methods on + * {@link IccFileHandler} passing a Message for onLoaded with the what field set to + * {@link #EVENT_GET_ICC_RECORD_DONE} and the obj field set to an instance + * of this interface. The {@link #handleMessage} method in this class will print a + * log message using {@link #getEfName()} and decrement {@link #recordsToLoad}. + * + * If the record load was successful, {@link #onRecordLoaded} will be called with the result. + * Otherwise, an error log message will be output by {@link #handleMessage} and + * {@link #onRecordLoaded} will not be called. + */ + public interface IccRecordLoaded { + String getEfName(); + void onRecordLoaded(AsyncResult ar); + } + // ***** Constructor public IccRecords(PhoneBase p) { @@ -234,7 +254,32 @@ public abstract class IccRecords extends Handler implements IccConstants { //***** Overridden from Handler @Override - public abstract void handleMessage(Message msg); + public void handleMessage(Message msg) { + switch (msg.what) { + case EVENT_GET_ICC_RECORD_DONE: + try { + AsyncResult ar = (AsyncResult) msg.obj; + IccRecordLoaded recordLoaded = (IccRecordLoaded) ar.userObj; + if (DBG) log(recordLoaded.getEfName() + " LOADED"); + + if (ar.exception != null) { + loge("Record Load Exception: " + ar.exception); + } else { + recordLoaded.onRecordLoaded(ar); + } + }catch (RuntimeException exc) { + // I don't want these exceptions to be fatal + loge("Exception parsing SIM record: " + exc); + } finally { + // Count up record load responses even if they are fails + onRecordLoaded(); + } + break; + + default: + super.handleMessage(msg); + } + } protected abstract void onRecordLoaded(); @@ -303,4 +348,19 @@ public abstract class IccRecords extends Handler implements IccConstants { * @param s is the string to write */ protected abstract void log(String s); + + /** + * Write error string to log file. + * + * @param s is the string to write + */ + protected abstract void loge(String s); + + /** + * Return an interface to retrieve the ISIM records for IMS, if available. + * @return the interface to retrieve the ISIM records, or null if not supported + */ + public IsimRecords getIsimRecords() { + return null; + } } diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java index 4b02e8e..6347f37 100644 --- a/telephony/java/com/android/internal/telephony/Phone.java +++ b/telephony/java/com/android/internal/telephony/Phone.java @@ -28,6 +28,7 @@ import android.telephony.ServiceState; import android.telephony.SignalStrength; import com.android.internal.telephony.DataConnection; +import com.android.internal.telephony.ims.IsimRecords; import com.android.internal.telephony.test.SimulatedRadioControl; import java.util.List; @@ -1730,4 +1731,20 @@ public interface Phone { * false otherwise */ boolean isCspPlmnEnabled(); + + /** + * Return an interface to retrieve the ISIM records for IMS, if available. + * @return the interface to retrieve the ISIM records, or null if not supported + */ + IsimRecords getIsimRecords(); + + /** + * Request the ISIM application on the UICC to perform the AKA + * challenge/response algorithm for IMS authentication. The nonce string + * and challenge response are Base64 encoded Strings. + * + * @param nonce the nonce string to pass with the ISIM authentication request + * @param response a callback message with the String response in the obj field + */ + void requestIsimAuthentication(String nonce, Message response); } diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java index a0961ca..4f86ea8 100644 --- a/telephony/java/com/android/internal/telephony/PhoneBase.java +++ b/telephony/java/com/android/internal/telephony/PhoneBase.java @@ -37,6 +37,7 @@ import android.text.TextUtils; import android.util.Log; import com.android.internal.R; +import com.android.internal.telephony.ims.IsimRecords; import com.android.internal.telephony.test.SimulatedRadioControl; import com.android.internal.telephony.gsm.SIMRecords; import com.android.internal.telephony.gsm.SimCard; @@ -1114,6 +1115,15 @@ public abstract class PhoneBase extends Handler implements Phone { return false; } + public IsimRecords getIsimRecords() { + Log.e(LOG_TAG, "getIsimRecords() is only supported on LTE devices"); + return null; + } + + public void requestIsimAuthentication(String nonce, Message result) { + Log.e(LOG_TAG, "requestIsimAuthentication() is only supported on LTE devices"); + } + /** * Common error logger method for unexpected calls to CDMA-only methods. */ diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java index b5bfc76f..3678017 100644 --- a/telephony/java/com/android/internal/telephony/PhoneProxy.java +++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java @@ -32,6 +32,7 @@ import android.util.Log; import com.android.internal.telephony.cdma.CDMAPhone; import com.android.internal.telephony.gsm.GSMPhone; +import com.android.internal.telephony.ims.IsimRecords; import com.android.internal.telephony.test.SimulatedRadioControl; import java.util.List; @@ -841,6 +842,14 @@ public class PhoneProxy extends Handler implements Phone { return mActivePhone.isCspPlmnEnabled(); } + public IsimRecords getIsimRecords() { + return mActivePhone.getIsimRecords(); + } + + public void requestIsimAuthentication(String nonce, Message response) { + mActivePhone.requestIsimAuthentication(nonce, response); + } + /** * {@inheritDoc} */ diff --git a/telephony/java/com/android/internal/telephony/PhoneSubInfo.java b/telephony/java/com/android/internal/telephony/PhoneSubInfo.java index a45cad1..de18d0a 100644 --- a/telephony/java/com/android/internal/telephony/PhoneSubInfo.java +++ b/telephony/java/com/android/internal/telephony/PhoneSubInfo.java @@ -24,15 +24,19 @@ import android.os.Binder; import android.telephony.PhoneNumberUtils; import android.util.Log; +import com.android.internal.telephony.ims.IsimRecords; + public class PhoneSubInfo extends IPhoneSubInfo.Stub { static final String LOG_TAG = "PHONE"; private Phone mPhone; private Context mContext; private static final String READ_PHONE_STATE = android.Manifest.permission.READ_PHONE_STATE; + // TODO: change getCompleteVoiceMailNumber() to require READ_PRIVILEGED_PHONE_STATE private static final String CALL_PRIVILEGED = - // TODO Add core/res/AndriodManifest.xml#READ_PRIVILEGED_PHONE_STATE android.Manifest.permission.CALL_PRIVILEGED; + private static final String READ_PRIVILEGED_PHONE_STATE = + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; public PhoneSubInfo(Phone phone) { mPhone = phone; @@ -131,6 +135,52 @@ public class PhoneSubInfo extends IPhoneSubInfo.Stub { return (String) mPhone.getVoiceMailAlphaTag(); } + /** + * Returns the IMS private user identity (IMPI) that was loaded from the ISIM. + * @return the IMPI, or null if not present or not loaded + */ + public String getIsimImpi() { + mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, + "Requires READ_PRIVILEGED_PHONE_STATE"); + IsimRecords isim = mPhone.getIsimRecords(); + if (isim != null) { + return isim.getIsimImpi(); + } else { + return null; + } + } + + /** + * Returns the IMS home network domain name that was loaded from the ISIM. + * @return the IMS domain name, or null if not present or not loaded + */ + public String getIsimDomain() { + mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, + "Requires READ_PRIVILEGED_PHONE_STATE"); + IsimRecords isim = mPhone.getIsimRecords(); + if (isim != null) { + return isim.getIsimDomain(); + } else { + return null; + } + } + + /** + * Returns the IMS public user identities (IMPU) that were loaded from the ISIM. + * @return an array of IMPU strings, with one IMPU per string, or null if + * not present or not loaded + */ + public String[] getIsimImpu() { + mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, + "Requires READ_PRIVILEGED_PHONE_STATE"); + IsimRecords isim = mPhone.getIsimRecords(); + if (isim != null) { + return isim.getIsimImpu(); + } else { + return null; + } + } + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { diff --git a/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java b/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java index 7009893..a287b2e 100644 --- a/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java +++ b/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java @@ -95,6 +95,31 @@ public class PhoneSubInfoProxy extends IPhoneSubInfo.Stub { return mPhoneSubInfo.getVoiceMailAlphaTag(); } + /** + * Returns the IMS private user identity (IMPI) that was loaded from the ISIM. + * @return the IMPI, or null if not present or not loaded + */ + public String getIsimImpi() { + return mPhoneSubInfo.getIsimImpi(); + } + + /** + * Returns the IMS home network domain name that was loaded from the ISIM. + * @return the IMS domain name, or null if not present or not loaded + */ + public String getIsimDomain() { + return mPhoneSubInfo.getIsimDomain(); + } + + /** + * Returns the IMS public user identities (IMPU) that were loaded from the ISIM. + * @return an array of IMPU strings, with one IMPU per string, or null if + * not present or not loaded + */ + public String[] getIsimImpu() { + return mPhoneSubInfo.getIsimImpu(); + } + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mPhoneSubInfo.dump(fd, pw, args); } diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java index c6ed405..3e13a86 100644 --- a/telephony/java/com/android/internal/telephony/RIL.java +++ b/telephony/java/com/android/internal/telephony/RIL.java @@ -47,17 +47,8 @@ import android.telephony.SmsMessage; import android.text.TextUtils; import android.util.Log; -import com.android.internal.telephony.CallForwardInfo; -import com.android.internal.telephony.CommandException; -import com.android.internal.telephony.DataCallState; import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; import com.android.internal.telephony.gsm.SuppServiceNotification; -import com.android.internal.telephony.IccCardApplication; -import com.android.internal.telephony.IccCardStatus; -import com.android.internal.telephony.IccUtils; -import com.android.internal.telephony.OperatorInfo; -import com.android.internal.telephony.RILConstants; -import com.android.internal.telephony.SmsResponse; import com.android.internal.telephony.cdma.CdmaCallWaitingNotification; import com.android.internal.telephony.cdma.CdmaInformationRecords; @@ -2255,6 +2246,7 @@ public final class RIL extends BaseCommands implements CommandsInterface { case RIL_REQUEST_REPORT_SMS_MEMORY_STATUS: ret = responseVoid(p); break; case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING: ret = responseVoid(p); break; case RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE: ret = responseInts(p); break; + case RIL_REQUEST_ISIM_AUTHENTICATION: ret = responseString(p); break; default: throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest); //break; @@ -3461,6 +3453,7 @@ public final class RIL extends BaseCommands implements CommandsInterface { case RIL_REQUEST_REPORT_SMS_MEMORY_STATUS: return "RIL_REQUEST_REPORT_SMS_MEMORY_STATUS"; case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING: return "RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING"; case RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE: return "RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE"; + case RIL_REQUEST_ISIM_AUTHENTICATION: return "RIL_REQUEST_ISIM_AUTHENTICATION"; default: return "<unknown request>"; } } @@ -3704,4 +3697,13 @@ public final class RIL extends BaseCommands implements CommandsInterface { send(rr); } + public void requestIsimAuthentication(String nonce, Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_ISIM_AUTHENTICATION, response); + + rr.mp.writeString(nonce); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } } diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index facee5f..7fb7f41 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -261,6 +261,7 @@ cat include/telephony/ril.h | \ int RIL_REQUEST_REPORT_SMS_MEMORY_STATUS = 102; int RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING = 103; int RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE = 104; + int RIL_REQUEST_ISIM_AUTHENTICATION = 105; int RIL_UNSOL_RESPONSE_BASE = 1000; int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000; int RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001; diff --git a/telephony/java/com/android/internal/telephony/cat/ResponseData.java b/telephony/java/com/android/internal/telephony/cat/ResponseData.java index 55a2b63..1157c1a 100644 --- a/telephony/java/com/android/internal/telephony/cat/ResponseData.java +++ b/telephony/java/com/android/internal/telephony/cat/ResponseData.java @@ -19,6 +19,10 @@ package com.android.internal.telephony.cat; import com.android.internal.telephony.EncodeException; import com.android.internal.telephony.GsmAlphabet; import java.util.Calendar; +import java.util.TimeZone; +import android.os.SystemProperties; +import android.text.TextUtils; + import com.android.internal.telephony.cat.AppInterface.CommandType; import java.io.ByteArrayOutputStream; @@ -209,7 +213,6 @@ class DTTZResponseData extends ResponseData { buf.write(tag); // tag byte[] data = new byte[8]; - byte btmp; // temp variable data[0] = 0x07; // Write length of DTTZ data @@ -217,41 +220,62 @@ class DTTZResponseData extends ResponseData { calendar = Calendar.getInstance(); } // Fill year byte - btmp = (byte) (calendar.get(java.util.Calendar.YEAR) % 100); - data[1] = (byte) (btmp / 10); - data[1] += (byte) ((btmp % 10) << 4); + data[1] = byteToBCD(calendar.get(java.util.Calendar.YEAR) % 100); // Fill month byte - btmp = (byte) (calendar.get(java.util.Calendar.MONTH) + 1); - data[2] = (byte) (btmp / 10); - data[2] += (byte) ((btmp % 10) << 4); + data[2] = byteToBCD(calendar.get(java.util.Calendar.MONTH) + 1); // Fill day byte - btmp = (byte) (calendar.get(java.util.Calendar.DATE)); - data[3] = (byte) (btmp / 10); - data[3] += (byte) ((btmp % 10) << 4); + data[3] = byteToBCD(calendar.get(java.util.Calendar.DATE)); // Fill hour byte - btmp = (byte) (calendar.get(java.util.Calendar.HOUR_OF_DAY)); - data[4] = (byte) (btmp / 10); - data[4] += (byte) ((btmp % 10) << 4); + data[4] = byteToBCD(calendar.get(java.util.Calendar.HOUR_OF_DAY)); // Fill minute byte - btmp = (byte) (calendar.get(java.util.Calendar.MINUTE)); - data[5] = (byte) (btmp / 10); - data[5] += (byte) ((btmp % 10) << 4); + data[5] = byteToBCD(calendar.get(java.util.Calendar.MINUTE)); // Fill second byte - btmp = (byte) (calendar.get(java.util.Calendar.SECOND)); - data[6] = (byte) (btmp / 10); - data[6] += (byte) ((btmp % 10) << 4); + data[6] = byteToBCD(calendar.get(java.util.Calendar.SECOND)); - // No time zone info - data[7] = (byte) 0xFF; + String tz = SystemProperties.get("persist.sys.timezone", ""); + if (TextUtils.isEmpty(tz)) { + data[7] = (byte) 0xFF; // set FF in terminal response + } else { + TimeZone zone = TimeZone.getTimeZone(tz); + int zoneOffset = zone.getRawOffset() + zone.getDSTSavings(); + data[7] = getTZOffSetByte(zoneOffset); + } for (byte b : data) { buf.write(b); } } + + private byte byteToBCD(int value) { + if (value < 0 && value > 99) { + CatLog.d(this, "Err: byteToBCD conversion Value is " + value + + " Value has to be between 0 and 99"); + return 0; + } + + return (byte) ((value / 10) | ((value % 10) << 4)); + } + + private byte getTZOffSetByte(long offSetVal) { + boolean isNegative = (offSetVal < 0); + + /* + * The 'offSetVal' is in milliseconds. Convert it to hours and compute + * offset While sending T.R to UICC, offset is expressed is 'quarters of + * hours' + */ + + long tzOffset = offSetVal / (15 * 60 * 1000); + tzOffset = (isNegative ? -1 : 1) * tzOffset; + byte bcdVal = byteToBCD((int) tzOffset); + // For negative offsets, put '1' in the msb + return isNegative ? (bcdVal |= 0x08) : bcdVal; + } + } diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java index ac66b48..f4ed91d 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 The Android Open Source Project + * 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. @@ -16,29 +16,19 @@ package com.android.internal.telephony.cdma; -import android.os.SystemProperties; +import android.content.ContentValues; import android.content.Context; +import android.database.SQLException; import android.net.Uri; -import android.content.Context; +import android.os.Message; import android.provider.Telephony; -import android.content.ContentValues; -import android.database.SQLException; -import android.telephony.ServiceState; -import android.telephony.SignalStrength; +import android.util.Log; -import com.android.internal.telephony.gsm.SIMRecords; -import com.android.internal.telephony.gsm.SimCard; -import com.android.internal.telephony.ServiceStateTracker; -import com.android.internal.telephony.DataConnectionTracker; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.Phone; -import com.android.internal.telephony.PhoneBase; import com.android.internal.telephony.PhoneNotifier; -import com.android.internal.telephony.PhoneProxy; -import com.android.internal.telephony.IccCard; -import com.android.internal.telephony.gsm.GsmDataConnectionTracker; - -import android.util.Log; +import com.android.internal.telephony.gsm.SimCard; +import com.android.internal.telephony.ims.IsimRecords; public class CDMALTEPhone extends CDMAPhone { static final String LOG_TAG = "CDMA"; @@ -68,7 +58,7 @@ public class CDMALTEPhone extends CDMAPhone { DataState ret = DataState.DISCONNECTED; if (mSST == null) { - // Radio Technology Change is ongoning, dispose() and + // Radio Technology Change is ongoing, dispose() and // removeReferences() have already been called ret = DataState.DISCONNECTED; @@ -146,6 +136,16 @@ public class CDMALTEPhone extends CDMAPhone { } @Override + public IsimRecords getIsimRecords() { + return mIccRecords.getIsimRecords(); + } + + @Override + public void requestIsimAuthentication(String nonce, Message result) { + mCM.requestIsimAuthentication(nonce, result); + } + + @Override protected void log(String s) { if (DBG) Log.d(LOG_TAG, "[CDMALTEPhone] " + s); diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java index b9d7c46..b57af0e 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java @@ -42,6 +42,10 @@ public final class CdmaLteUiccFileHandler extends IccFileHandler { return MF_SIM + DF_CDMA; case EF_AD: return MF_SIM + DF_GSM; + case EF_IMPI: + case EF_DOMAIN: + case EF_IMPU: + return MF_SIM + DF_ADFISIM; } return getCommonIccEFPath(efid); } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java index fc6abad..c4fa6f6 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java @@ -15,8 +15,10 @@ */ package com.android.internal.telephony.cdma; -import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA; -import static com.android.internal.telephony.TelephonyProperties.PROPERTY_TEST_CSIM; +import android.os.AsyncResult; +import android.os.SystemProperties; +import android.util.Log; + import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.IccCardApplication.AppType; import com.android.internal.telephony.IccFileHandler; @@ -25,12 +27,14 @@ import com.android.internal.telephony.MccTable; 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; -import java.util.Locale; +import com.android.internal.telephony.ims.IsimRecords; +import com.android.internal.telephony.ims.IsimUiccRecords; + import java.util.ArrayList; +import java.util.Locale; + +import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA; +import static com.android.internal.telephony.TelephonyProperties.PROPERTY_TEST_CSIM; /** * {@hide} @@ -46,130 +50,191 @@ public final class CdmaLteUiccRecords extends SIMRecords { 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; + private final IsimUiccRecords mIsimUiccRecords = new IsimUiccRecords(); public CdmaLteUiccRecords(PhoneBase p) { super(p); } - @Override - public void handleMessage(Message msg) { - AsyncResult ar; - byte data[]; - - boolean isCsimRecordLoadResponse = false; + // Refer to ETSI TS 102.221 + private class EfPlLoaded implements IccRecordLoaded { + public String getEfName() { + return "EF_PL"; + } - 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; + public void onRecordLoaded(AsyncResult ar) { + mEFpl = (byte[]) ar.result; + if (DBG) log("EF_PL=" + IccUtils.bytesToHexString(mEFpl)); + } + } - ar = (AsyncResult) msg.obj; + // Refer to C.S0065 5.2.26 + private class EfCsimLiLoaded implements IccRecordLoaded { + public String getEfName() { + return "EF_CSIM_LI"; + } - if (ar.exception != null) { - Log.e(LOG_TAG, "ar.exception = " + ar.exception); - break; + public void onRecordLoaded(AsyncResult ar) { + 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] = ' '; } + } - mEFpl = (byte[]) ar.result; - if (DBG) log("EF_PL=" + IccUtils.bytesToHexString(mEFpl)); - break; + if (DBG) log("EF_LI=" + IccUtils.bytesToHexString(mEFli)); + } + } - case EVENT_GET_CSIM_LI_DONE: - // Refer to C.S0065 5.2.26 - if (DBG) log("EVENT_GET_CSIM_LI_DONE"); - isCsimRecordLoadResponse = true; + // Refer to C.S0065 5.2.32 + private class EfCsimSpnLoaded implements IccRecordLoaded { + public String getEfName() { + return "EF_CSIM_SPN"; + } - ar = (AsyncResult) msg.obj; - if (ar.exception != null) { - Log.e(LOG_TAG, "ar.exception = " + ar.exception); - break; - } + public void onRecordLoaded(AsyncResult ar) { + byte[] data = (byte[]) ar.result; + if (DBG) log("CSIM_SPN=" + + IccUtils.bytesToHexString(data)); - 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] = ' '; - } - } + // C.S0065 for EF_SPN decoding + mCsimSpnDisplayCondition = ((0x01 & data[0]) != 0); - 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; + 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); - if (ar.exception != null) { - Log.e(LOG_TAG, "ar.exception=" + ar.exception); - break; - } - 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); + 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; - } - 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); + case UserData.ENCODING_IA5: + case UserData.ENCODING_GSM_7BIT_ALPHABET: + case UserData.ENCODING_7BIT_ASCII: + spn = GsmAlphabet.gsm7BitPackedToString(spnData, 0, (numBytes*8)/7); 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); + case UserData.ENCODING_UNICODE_16: + spn = new String(spnData, 0, numBytes, "utf-16"); break; + default: + log("SPN encoding not supported"); } - 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; + } catch(Exception e) { + log("spn decode error: " + e); + } + if (DBG) log("spn=" + spn); + if (DBG) log("spnCondition=" + mCsimSpnDisplayCondition); + phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, spn); + } + } + + private class EfCsimMdnLoaded implements IccRecordLoaded { + public String getEfName() { + return "EF_CSIM_MDN"; + } + + public void onRecordLoaded(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 class EfCsimImsimLoaded implements IccRecordLoaded { + public String getEfName() { + return "EF_CSIM_IMSIM"; + } + + public void onRecordLoaded(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)); + mMin = builder.toString(); + if (DBG) log("min present=" + mMin); + } else { + if (DBG) log("min not present"); + } + } + } + + private class EfCsimCdmaHomeLoaded implements IccRecordLoaded { + public String getEfName() { + return "EF_CSIM_CDMAHOME"; + } + + public void onRecordLoaded(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(','); } - onGetCSimEprlDone(ar); - break; - default: - super.handleMessage(msg); - }}catch (RuntimeException exc) { - Log.w(LOG_TAG, "Exception parsing SIM record", exc); - } finally { - if (isCsimRecordLoadResponse) { - onRecordLoaded(); } + // remove trailing "," + sidBuf.setLength(sidBuf.length()-1); + nidBuf.setLength(nidBuf.length()-1); + + mHomeSystemId = sidBuf.toString(); + mHomeNetworkId = nidBuf.toString(); + } + } + + private class EfCsimEprlLoaded implements IccRecordLoaded { + public String getEfName() { + return "EF_CSIM_EPRL"; + } + public void onRecordLoaded(AsyncResult ar) { + onGetCSimEprlDone(ar); } } @@ -189,8 +254,8 @@ public final class CdmaLteUiccRecords extends SIMRecords { @Override protected void onAllRecordsLoaded() { - super.onAllRecordsLoaded(); setLocaleFromCsim(); + super.onAllRecordsLoaded(); // broadcasts ICC state change to "LOADED" } @Override @@ -207,112 +272,36 @@ public final class CdmaLteUiccRecords extends SIMRecords { iccFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE)); recordsToLoad++; - iccFh.loadEFTransparent(EF_PL, obtainMessage(EVENT_GET_PL_DONE)); + iccFh.loadEFTransparent(EF_PL, + obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfPlLoaded())); recordsToLoad++; - iccFh.loadEFTransparent(EF_CSIM_LI, obtainMessage(EVENT_GET_CSIM_LI_DONE)); + iccFh.loadEFTransparent(EF_CSIM_LI, + obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimLiLoaded())); recordsToLoad++; - iccFh.loadEFTransparent(EF_CSIM_SPN, obtainMessage(EVENT_GET_CSIM_SPN_DONE)); + iccFh.loadEFTransparent(EF_CSIM_SPN, + obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimSpnLoaded())); recordsToLoad++; - iccFh.loadEFLinearFixed(EF_CSIM_MDN, 1, obtainMessage(EVENT_GET_CSIM_MDN_DONE)); + iccFh.loadEFLinearFixed(EF_CSIM_MDN, 1, + obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimMdnLoaded())); recordsToLoad++; - iccFh.loadEFTransparent(EF_CSIM_IMSIM, obtainMessage(EVENT_GET_CSIM_IMSIM_DONE)); + iccFh.loadEFTransparent(EF_CSIM_IMSIM, + obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimImsimLoaded())); recordsToLoad++; iccFh.loadEFLinearFixedAll(EF_CSIM_CDMAHOME, - obtainMessage(EVENT_GET_CSIM_CDMAHOME_DONE)); + obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimCdmaHomeLoaded())); recordsToLoad++; - iccFh.loadEFTransparent(EF_CSIM_EPRL, obtainMessage(EVENT_GET_CSIM_EPRL_DONE)); + iccFh.loadEFTransparent(EF_CSIM_EPRL, + obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimEprlLoaded())); 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 - mCsimSpnDisplayCondition = ((0x01 & 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=" + mCsimSpnDisplayCondition); - 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"); - } + // load ISIM records + recordsToLoad += mIsimUiccRecords.fetchIsimRecords(iccFh, this); } private int adjstMinDigits (int digits) { @@ -324,32 +313,6 @@ public final class CdmaLteUiccRecords extends SIMRecords { 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. @@ -418,6 +381,11 @@ public final class CdmaLteUiccRecords extends SIMRecords { if (DBG) Log.d(LOG_TAG, "[CSIM] " + s); } + @Override + protected void loge(String s) { + if (DBG) Log.e(LOG_TAG, "[CSIM] " + s); + } + public String getMdn() { return mMdn; } @@ -443,6 +411,11 @@ public final class CdmaLteUiccRecords extends SIMRecords { } @Override + public IsimRecords getIsimRecords() { + return mIsimUiccRecords; + } + + @Override public boolean isProvisioned() { // If UICC card has CSIM app, look for MDN and MIN field // to determine if the SIM is provisioned. Otherwise, diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java index 9af2d26..9850b9f 100755 --- a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java +++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java @@ -443,4 +443,8 @@ public final class RuimRecords extends IccRecords { Log.d(LOG_TAG, "[RuimRecords] " + s); } + @Override + protected void loge(String s) { + Log.e(LOG_TAG, "[RuimRecords] " + s); + } } diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java index b0bad56..28034cc 100755 --- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java +++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java @@ -147,8 +147,6 @@ public 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 = { @@ -1089,6 +1087,9 @@ public class SIMRecords extends IccRecords { handleEfCspData(data); break; + default: + super.handleMessage(msg); // IccRecords handles generic record load responses + }}catch (RuntimeException exc) { // I don't want these exceptions to be fatal Log.w(LOG_TAG, "Exception parsing SIM record", exc); @@ -1573,6 +1574,10 @@ public class SIMRecords extends IccRecords { Log.d(LOG_TAG, "[SIMRecords] " + s); } + protected void loge(String s) { + Log.e(LOG_TAG, "[SIMRecords] " + s); + } + /** * Return true if "Restriction of menu options for manual PLMN selection" * bit is set or EF_CSP data is unavailable, return false otherwise. diff --git a/telephony/java/com/android/internal/telephony/ims/IsimRecords.java b/telephony/java/com/android/internal/telephony/ims/IsimRecords.java new file mode 100644 index 0000000..b8b98b9 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/ims/IsimRecords.java @@ -0,0 +1,44 @@ +/* + * 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.ims; + +/** + * {@hide} + */ +public interface IsimRecords { + + /** + * Return the IMS private user identity (IMPI). + * Returns null if the IMPI hasn't been loaded or isn't present on the ISIM. + * @return the IMS private user identity string, or null if not available + */ + String getIsimImpi(); + + /** + * Return the IMS home network domain name. + * Returns null if the IMS domain hasn't been loaded or isn't present on the ISIM. + * @return the IMS home network domain name, or null if not available + */ + String getIsimDomain(); + + /** + * Return an array of IMS public user identities (IMPU). + * Returns null if the IMPU hasn't been loaded or isn't present on the ISIM. + * @return an array of IMS public user identity strings, or null if not available + */ + String[] getIsimImpu(); +} diff --git a/telephony/java/com/android/internal/telephony/ims/IsimUiccRecords.java b/telephony/java/com/android/internal/telephony/ims/IsimUiccRecords.java new file mode 100644 index 0000000..ee1a42d --- /dev/null +++ b/telephony/java/com/android/internal/telephony/ims/IsimUiccRecords.java @@ -0,0 +1,157 @@ +/* + * 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.ims; + +import android.os.AsyncResult; +import android.os.Handler; +import android.util.Log; + +import com.android.internal.telephony.IccFileHandler; +import com.android.internal.telephony.IccRecords; +import com.android.internal.telephony.gsm.SimTlv; + +import java.nio.charset.Charset; +import java.util.ArrayList; + +import static com.android.internal.telephony.IccConstants.EF_DOMAIN; +import static com.android.internal.telephony.IccConstants.EF_IMPI; +import static com.android.internal.telephony.IccConstants.EF_IMPU; + +/** + * {@hide} + */ +public final class IsimUiccRecords implements IsimRecords { + protected static final String LOG_TAG = "GSM"; + + private static final boolean DBG = true; + private static final boolean DUMP_RECORDS = false; // Note: PII is logged when this is true + + // ISIM EF records (see 3GPP TS 31.103) + private String mIsimImpi; // IMS private user identity + private String mIsimDomain; // IMS home network domain name + private String[] mIsimImpu; // IMS public user identity(s) + + private static final int TAG_ISIM_VALUE = 0x80; // From 3GPP TS 31.103 + + private class EfIsimImpiLoaded implements IccRecords.IccRecordLoaded { + public String getEfName() { + return "EF_ISIM_IMPI"; + } + public void onRecordLoaded(AsyncResult ar) { + byte[] data = (byte[]) ar.result; + mIsimImpi = isimTlvToString(data); + if (DUMP_RECORDS) log("EF_IMPI=" + mIsimImpi); + } + } + + private class EfIsimImpuLoaded implements IccRecords.IccRecordLoaded { + public String getEfName() { + return "EF_ISIM_IMPU"; + } + public void onRecordLoaded(AsyncResult ar) { + ArrayList<byte[]> impuList = (ArrayList<byte[]>) ar.result; + if (DBG) log("EF_IMPU record count: " + impuList.size()); + mIsimImpu = new String[impuList.size()]; + int i = 0; + for (byte[] identity : impuList) { + String impu = isimTlvToString(identity); + if (DUMP_RECORDS) log("EF_IMPU[" + i + "]=" + impu); + mIsimImpu[i++] = impu; + } + } + } + + private class EfIsimDomainLoaded implements IccRecords.IccRecordLoaded { + public String getEfName() { + return "EF_ISIM_DOMAIN"; + } + public void onRecordLoaded(AsyncResult ar) { + byte[] data = (byte[]) ar.result; + mIsimDomain = isimTlvToString(data); + if (DUMP_RECORDS) log("EF_DOMAIN=" + mIsimDomain); + } + } + + /** + * Request the ISIM records to load. + * @param iccFh the IccFileHandler to load the records from + * @param h the Handler to which the response message will be sent + * @return the number of EF record requests that were added + */ + public int fetchIsimRecords(IccFileHandler iccFh, Handler h) { + iccFh.loadEFTransparent(EF_IMPI, h.obtainMessage( + IccRecords.EVENT_GET_ICC_RECORD_DONE, new EfIsimImpiLoaded())); + iccFh.loadEFLinearFixedAll(EF_IMPU, h.obtainMessage( + IccRecords.EVENT_GET_ICC_RECORD_DONE, new EfIsimImpuLoaded())); + iccFh.loadEFTransparent(EF_DOMAIN, h.obtainMessage( + IccRecords.EVENT_GET_ICC_RECORD_DONE, new EfIsimDomainLoaded())); + return 3; // number of EF record load requests + } + + /** + * ISIM records for IMS are stored inside a Tag-Length-Value record as a UTF-8 string + * with tag value 0x80. + * @param record the byte array containing the IMS data string + * @return the decoded String value, or null if the record can't be decoded + */ + private static String isimTlvToString(byte[] record) { + SimTlv tlv = new SimTlv(record, 0, record.length); + do { + if (tlv.getTag() == TAG_ISIM_VALUE) { + return new String(tlv.getData(), Charset.forName("UTF-8")); + } + } while (tlv.nextObject()); + + Log.e(LOG_TAG, "[ISIM] can't find TLV tag in ISIM record, returning null"); + return null; + } + + void log(String s) { + if (DBG) Log.d(LOG_TAG, "[ISIM] " + s); + } + + void loge(String s) { + if (DBG) Log.e(LOG_TAG, "[ISIM] " + s); + } + + /** + * Return the IMS private user identity (IMPI). + * Returns null if the IMPI hasn't been loaded or isn't present on the ISIM. + * @return the IMS private user identity string, or null if not available + */ + public String getIsimImpi() { + return mIsimImpi; + } + + /** + * Return the IMS home network domain name. + * Returns null if the IMS domain hasn't been loaded or isn't present on the ISIM. + * @return the IMS home network domain name, or null if not available + */ + public String getIsimDomain() { + return mIsimDomain; + } + + /** + * Return an array of IMS public user identities (IMPU). + * Returns null if the IMPU hasn't been loaded or isn't present on the ISIM. + * @return an array of IMS public user identity strings, or null if not available + */ + public String[] getIsimImpu() { + return (mIsimImpu != null) ? mIsimImpu.clone() : null; + } +} diff --git a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java index 5208ccd..85ce6e0 100644 --- a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java +++ b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java @@ -186,7 +186,7 @@ class SipCommandInterface extends BaseCommands implements CommandsInterface { public void setupDataCall(String radioTechnology, String profile, String apn, String user, String password, String authType, - String protcol, Message result) { + String protocol, Message result) { } public void deactivateDataCall(int cid, int reason, Message result) { @@ -403,4 +403,7 @@ class SipCommandInterface extends BaseCommands implements CommandsInterface { public void changeIccPin2ForApp(String oldPin2, String newPin2, String aidPtr, Message response) { } + + public void requestIsimAuthentication(String nonce, Message response) { + } } diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java index 80de9f3..a2a344f 100644 --- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java +++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java @@ -1501,4 +1501,8 @@ public final class SimulatedCommands extends BaseCommands Message response) { unimplemented(response); } + + public void requestIsimAuthentication(String nonce, Message response) { + unimplemented(response); + } } |