aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Harold <nharold@google.com>2016-12-09 00:52:34 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2016-12-09 00:52:35 +0000
commit989b241af992d17d1e2be6097149cf764751c7b7 (patch)
tree97c9186cd6913300364d0a3a444eb8950fd8ae3a
parent8362fc5960ac919b799628e853a7ba5bbf4521da (diff)
parent229d3318ca022dcda540a86b9f60bb314c78998b (diff)
downloadandroid_frameworks_opt_telephony-989b241af992d17d1e2be6097149cf764751c7b7.tar.gz
android_frameworks_opt_telephony-989b241af992d17d1e2be6097149cf764751c7b7.tar.bz2
android_frameworks_opt_telephony-989b241af992d17d1e2be6097149cf764751c7b7.zip
Merge changes from topic 'dump-sim-plmn-records' into nyc-mr2-dev
* changes: Add PLMN Selection Info to SIM Records Add meaningful error strings to IccIoResult Cleanup of IccConstants and SIMRecords Constants
-rw-r--r--src/java/com/android/internal/telephony/uicc/IccConstants.java57
-rw-r--r--src/java/com/android/internal/telephony/uicc/IccFileHandler.java8
-rw-r--r--src/java/com/android/internal/telephony/uicc/IccIoResult.java145
-rw-r--r--src/java/com/android/internal/telephony/uicc/IccRecords.java40
-rw-r--r--src/java/com/android/internal/telephony/uicc/IccUtils.java23
-rw-r--r--src/java/com/android/internal/telephony/uicc/PlmnActRecord.java144
-rw-r--r--src/java/com/android/internal/telephony/uicc/SIMFileHandler.java2
-rw-r--r--src/java/com/android/internal/telephony/uicc/SIMRecords.java191
-rw-r--r--src/java/com/android/internal/telephony/uicc/UsimFileHandler.java7
9 files changed, 532 insertions, 85 deletions
diff --git a/src/java/com/android/internal/telephony/uicc/IccConstants.java b/src/java/com/android/internal/telephony/uicc/IccConstants.java
index 061b28f8c..970bf358e 100644
--- a/src/java/com/android/internal/telephony/uicc/IccConstants.java
+++ b/src/java/com/android/internal/telephony/uicc/IccConstants.java
@@ -30,21 +30,21 @@ public interface IccConstants {
static final int EF_EXT2 = 0x6F4B;
static final int EF_EXT3 = 0x6F4C;
static final int EF_EXT5 = 0x6F4E;
- static final int EF_EXT6 = 0x6fc8; // Ext record for EF[MBDN]
+ static final int EF_EXT6 = 0x6FC8; // Ext record for EF[MBDN]
static final int EF_MWIS = 0x6FCA;
- static final int EF_MBDN = 0x6fc7;
- static final int EF_PNN = 0x6fc5;
- static final int EF_OPL = 0x6fc6;
+ static final int EF_MBDN = 0x6FC7;
+ static final int EF_PNN = 0x6FC5;
+ static final int EF_OPL = 0x6FC6;
static final int EF_SPN = 0x6F46;
static final int EF_SMS = 0x6F3C;
- static final int EF_ICCID = 0x2fe2;
+ static final int EF_ICCID = 0x2FE2;
static final int EF_AD = 0x6FAD;
- static final int EF_MBI = 0x6fc9;
- static final int EF_MSISDN = 0x6f40;
- static final int EF_SPDI = 0x6fcd;
- static final int EF_SST = 0x6f38;
+ static final int EF_MBI = 0x6FC9;
+ static final int EF_MSISDN = 0x6F40;
+ static final int EF_SPDI = 0x6FCD;
+ static final int EF_SST = 0x6F38;
static final int EF_CFIS = 0x6FCB;
- static final int EF_IMG = 0x4f20;
+ static final int EF_IMG = 0x4F20;
// USIM SIM file ids from TS 131.102
public static final int EF_PBR = 0x4F30;
@@ -54,13 +54,13 @@ public interface IccConstants {
static final int EF_MAILBOX_CPHS = 0x6F17;
static final int EF_VOICE_MAIL_INDICATOR_CPHS = 0x6F11;
static final int EF_CFF_CPHS = 0x6F13;
- static final int EF_SPN_CPHS = 0x6f14;
- static final int EF_SPN_SHORT_CPHS = 0x6f18;
- static final int EF_INFO_CPHS = 0x6f16;
- static final int EF_CSP_CPHS = 0x6f15;
+ static final int EF_SPN_CPHS = 0x6F14;
+ static final int EF_SPN_SHORT_CPHS = 0x6F18;
+ static final int EF_INFO_CPHS = 0x6F16;
+ static final int EF_CSP_CPHS = 0x6F15;
// CDMA RUIM file ids from 3GPP2 C.S0023-0
- static final int EF_CST = 0x6f32;
+ static final int EF_CST = 0x6F32;
static final int EF_RUIM_SPN =0x6F41;
// ETSI TS.102.221
@@ -75,12 +75,27 @@ public interface IccConstants {
static final int EF_CSIM_MIPUPP = 0x6F4D;
//ISIM access
- static final int EF_IMPU = 0x6f04;
- static final int EF_IMPI = 0x6f02;
- static final int EF_DOMAIN = 0x6f03;
- static final int EF_IST = 0x6f07;
- static final int EF_PCSCF = 0x6f09;
- static final int EF_PSI = 0x6fe5;
+ static final int EF_IMPU = 0x6F04;
+ static final int EF_IMPI = 0x6F02;
+ static final int EF_DOMAIN = 0x6F03;
+ static final int EF_IST = 0x6F07;
+ static final int EF_PCSCF = 0x6F09;
+ static final int EF_PSI = 0x6FE5;
+
+ //PLMN Selection Information w/ Access Technology TS 131.102
+ static final int EF_PLMN_W_ACT = 0x6F60;
+ static final int EF_OPLMN_W_ACT = 0x6F61;
+ static final int EF_HPLMN_W_ACT = 0x6F62;
+
+ //Equivalent Home and Forbidden PLMN Lists TS 131.102
+ static final int EF_EHPLMN = 0x6FD9;
+ static final int EF_FPLMN = 0x6F7B;
+
+ // Last Roaming Selection Indicator
+ static final int EF_LRPLMNSI = 0x6FDC;
+
+ //Search interval for higher priority PLMNs
+ static final int EF_HPPLMN = 0x6F31;
// SMS record length from TS 51.011 10.5.3
static public final int SMS_RECORD_LENGTH = 176;
diff --git a/src/java/com/android/internal/telephony/uicc/IccFileHandler.java b/src/java/com/android/internal/telephony/uicc/IccFileHandler.java
index 881b4c3e6..4750814ff 100644
--- a/src/java/com/android/internal/telephony/uicc/IccFileHandler.java
+++ b/src/java/com/android/internal/telephony/uicc/IccFileHandler.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony.uicc;
import android.os.*;
+
import com.android.internal.telephony.CommandsInterface;
import java.util.ArrayList;
@@ -25,6 +26,7 @@ import java.util.ArrayList;
* {@hide}
*/
public abstract class IccFileHandler extends Handler implements IccConstants {
+ private static final boolean VDBG = false;
//from TS 11.11 9.1 or elsewhere
static protected final int COMMAND_READ_BINARY = 0xb0;
@@ -516,6 +518,11 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
fileid = msg.arg1;
+ if (VDBG) {
+ logd(String.format("Contents of the Select Response for command %x: ", fileid)
+ + IccUtils.bytesToHexString(data));
+ }
+
if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
throw new IccFileTypeMismatch();
}
@@ -628,7 +635,6 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
protected abstract String getEFPath(int efid);
protected abstract void logd(String s);
-
protected abstract void loge(String s);
}
diff --git a/src/java/com/android/internal/telephony/uicc/IccIoResult.java b/src/java/com/android/internal/telephony/uicc/IccIoResult.java
index 6f0b5c3fd..4a35e1460 100644
--- a/src/java/com/android/internal/telephony/uicc/IccIoResult.java
+++ b/src/java/com/android/internal/telephony/uicc/IccIoResult.java
@@ -22,6 +22,147 @@ package com.android.internal.telephony.uicc;
*/
public class
IccIoResult {
+
+ private static final String UNKNOWN_ERROR = "unknown";
+
+ private String getErrorString() {
+ // Errors from 3gpp 11.11 9.4.1
+ // Additional Errors from ETSI 102.221
+ //
+ // All error codes below are copied directly from their respective specification
+ // without modification except in cases where necessary string formatting has been omitted.
+ switch(sw1) {
+ case 0x62:
+ switch(sw2) {
+ case 0x00: return "No information given,"
+ + " state of non volatile memory unchanged";
+ case 0x81: return "Part of returned data may be corrupted";
+ case 0x82: return "End of file/record reached before reading Le bytes";
+ case 0x83: return "Selected file invalidated";
+ case 0x84: return "Selected file in termination state";
+ case 0xF1: return "More data available";
+ case 0xF2: return "More data available and proactive command pending";
+ case 0xF3: return "Response data available";
+ }
+ break;
+ case 0x63:
+ if (sw2 >> 4 == 0x0C) {
+ return "Command successful but after using an internal"
+ + "update retry routine but Verification failed";
+ }
+ switch(sw2) {
+ case 0xF1: return "More data expected";
+ case 0xF2: return "More data expected and proactive command pending";
+ }
+ break;
+ case 0x64:
+ switch(sw2) {
+ case 0x00: return "No information given,"
+ + " state of non-volatile memory unchanged";
+ }
+ break;
+ case 0x65:
+ switch(sw2) {
+ case 0x00: return "No information given, state of non-volatile memory changed";
+ case 0x81: return "Memory problem";
+ }
+ break;
+ case 0x67:
+ switch(sw2) {
+ case 0x00: return "incorrect parameter P3";
+ default: return "The interpretation of this status word is command dependent";
+ }
+ // break;
+ case 0x6B: return "incorrect parameter P1 or P2";
+ case 0x6D: return "unknown instruction code given in the command";
+ case 0x6E: return "wrong instruction class given in the command";
+ case 0x6F:
+ switch(sw2) {
+ case 0x00: return "technical problem with no diagnostic given";
+ default: return "The interpretation of this status word is command dependent";
+ }
+ // break;
+ case 0x68:
+ switch(sw2) {
+ case 0x00: return "No information given";
+ case 0x81: return "Logical channel not supported";
+ case 0x82: return "Secure messaging not supported";
+ }
+ break;
+ case 0x69:
+ switch(sw2) {
+ case 0x00: return "No information given";
+ case 0x81: return "Command incompatible with file structure";
+ case 0x82: return "Security status not satisfied";
+ case 0x83: return "Authentication/PIN method blocked";
+ case 0x84: return "Referenced data invalidated";
+ case 0x85: return "Conditions of use not satisfied";
+ case 0x86: return "Command not allowed (no EF selected)";
+ case 0x89: return "Command not allowed - secure channel -"
+ + " security not satisfied";
+ }
+ break;
+ case 0x6A:
+ switch(sw2) {
+ case 0x80: return "Incorrect parameters in the data field";
+ case 0x81: return "Function not supported";
+ case 0x82: return "File not found";
+ case 0x83: return "Record not found";
+ case 0x84: return "Not enough memory space";
+ case 0x86: return "Incorrect parameters P1 to P2";
+ case 0x87: return "Lc inconsistent with P1 to P2";
+ case 0x88: return "Referenced data not found";
+ }
+ break;
+ case 0x90: return null; // success
+ case 0x91: return null; // success
+ //Status Code 0x92 has contradictory meanings from 11.11 and 102.221 10.2.1.1
+ case 0x92:
+ if (sw2 >> 4 == 0) {
+ return "command successful but after using an internal update retry routine";
+ }
+ switch(sw2) {
+ case 0x40: return "memory problem";
+ }
+ break;
+ case 0x93:
+ switch(sw2) {
+ case 0x00:
+ return "SIM Application Toolkit is busy. Command cannot be executed"
+ + " at present, further normal commands are allowed.";
+ }
+ break;
+ case 0x94:
+ switch(sw2) {
+ case 0x00: return "no EF selected";
+ case 0x02: return "out f range (invalid address)";
+ case 0x04: return "file ID not found/pattern not found";
+ case 0x08: return "file is inconsistent with the command";
+ }
+ break;
+ case 0x98:
+ switch(sw2) {
+ case 0x02: return "no CHV initialized";
+ case 0x04: return "access condition not fulfilled/"
+ + "unsuccessful CHV verification, at least one attempt left/"
+ + "unsuccessful UNBLOCK CHV verification, at least one attempt left/"
+ + "authentication failed";
+ case 0x08: return "in contradiction with CHV status";
+ case 0x10: return "in contradiction with invalidation status";
+ case 0x40: return "unsuccessful CHV verification, no attempt left/"
+ + "unsuccessful UNBLOCK CHV verification, no attempt left/"
+ + "CHV blocked"
+ + "UNBLOCK CHV blocked";
+ case 0x50: return "increase cannot be performed, Max value reached";
+ }
+ break;
+ case 0x9E: return null; // success
+ case 0x9F: return null; // success
+ }
+ return UNKNOWN_ERROR;
+ }
+
+
public int sw1;
public int sw2;
@@ -39,8 +180,8 @@ IccIoResult {
@Override
public String toString() {
- return "IccIoResponse sw1:0x" + Integer.toHexString(sw1) + " sw2:0x"
- + Integer.toHexString(sw2);
+ return "IccIoResult sw1:0x" + Integer.toHexString(sw1) + " sw2:0x"
+ + Integer.toHexString(sw2) + ((!success()) ? " Error: " + getErrorString() : "");
}
/**
diff --git a/src/java/com/android/internal/telephony/uicc/IccRecords.java b/src/java/com/android/internal/telephony/uicc/IccRecords.java
index af54e6b37..6bbecfe85 100644
--- a/src/java/com/android/internal/telephony/uicc/IccRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/IccRecords.java
@@ -22,6 +22,7 @@ import android.os.Handler;
import android.os.Message;
import android.os.Registrant;
import android.os.RegistrantList;
+
import android.telephony.Rlog;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
@@ -88,6 +89,13 @@ public abstract class IccRecords extends Handler implements IccConstants {
protected String mGid2;
protected String mPrefLang;
+ protected PlmnActRecord[] mHplmnActRecords;
+ protected PlmnActRecord[] mOplmnActRecords;
+ protected PlmnActRecord[] mPlmnActRecords;
+
+ protected String[] mEhplmns;
+ protected String[] mFplmns;
+
private final Object mLock = new Object();
// ***** Constants
@@ -101,7 +109,6 @@ public abstract class IccRecords extends Handler implements IccConstants {
public static final int SPN_RULE_SHOW_PLMN = 0x02;
// ***** Event Constants
- protected static final int EVENT_SET_MSISDN_DONE = 30;
public static final int EVENT_MWI = 0; // Message Waiting indication
public static final int EVENT_CFI = 1; // Call Forwarding indication
public static final int EVENT_SPN = 2; // Service Provider Name
@@ -320,34 +327,13 @@ public abstract class IccRecords extends Handler implements IccConstants {
return null;
}
- /**
- * Set subscriber number to SIM record
- *
- * The subscriber number is stored in EF_MSISDN (TS 51.011)
- *
- * When the operation is complete, onComplete will be sent to its handler
- *
- * @param alphaTag alpha-tagging of the dailing nubmer (up to 10 characters)
- * @param number dailing nubmer (up to 20 digits)
- * if the number starts with '+', then set to international TOA
- * @param onComplete
- * onComplete.obj will be an AsyncResult
- * ((AsyncResult)onComplete.obj).exception == null on success
- * ((AsyncResult)onComplete.obj).exception != null on fail
- */
public void setMsisdnNumber(String alphaTag, String number,
Message onComplete) {
-
- mMsisdn = number;
- mMsisdnTag = alphaTag;
-
- if (DBG) log("Set MSISDN: " + mMsisdnTag +" " + mMsisdn);
-
-
- AdnRecord adn = new AdnRecord(mMsisdnTag, mMsisdn);
-
- new AdnRecordLoader(mFh).updateEF(adn, EF_MSISDN, EF_EXT1, 1, null,
- obtainMessage(EVENT_SET_MSISDN_DONE, onComplete));
+ loge("setMsisdn() should not be invoked on base IccRecords");
+ // synthesize a "File Not Found" exception and return it
+ AsyncResult.forMessage(onComplete).exception =
+ (new IccIoResult(0x6A, 0x82, (byte[]) null)).getException();
+ onComplete.sendToTarget();
}
public String getMsisdnAlphaTag() {
diff --git a/src/java/com/android/internal/telephony/uicc/IccUtils.java b/src/java/com/android/internal/telephony/uicc/IccUtils.java
index fdcc12537..67de87f2b 100644
--- a/src/java/com/android/internal/telephony/uicc/IccUtils.java
+++ b/src/java/com/android/internal/telephony/uicc/IccUtils.java
@@ -23,6 +23,7 @@ import android.graphics.Color;
import android.telephony.Rlog;
import com.android.internal.telephony.GsmAlphabet;
+
import java.io.UnsupportedEncodingException;
/**
@@ -61,6 +62,28 @@ public class IccUtils {
}
/**
+ * PLMN (MCC/MNC) is encoded as per 24.008 10.5.1.3
+ * Returns a concatenated string of MCC+MNC, stripping
+ * a trailing character for a 2-digit MNC
+ */
+ public static String bcdPlmnToString(byte[] data, int offset) {
+ if (offset + 3 > data.length) {
+ return null;
+ }
+ byte[] trans = new byte[3];
+ trans[0] = (byte) ((data[0 + offset] << 4) | ((data[0 + offset] >> 4) & 0xF));
+ trans[1] = (byte) ((data[1 + offset] << 4) | (data[2 + offset] & 0xF));
+ trans[2] = (byte) ((data[2 + offset] & 0xF0) | ((data[1 + offset] >> 4) & 0xF));
+ String ret = bytesToHexString(trans);
+
+ // For a 2-digit MNC we trim the trailing 'f'
+ if (ret.endsWith("f")) {
+ ret = ret.substring(0, ret.length() - 1);
+ }
+ return ret;
+ }
+
+ /**
* Some fields (like ICC ID) in GSM SIMs are stored as nibble-swizzled BCH
*/
public static String
diff --git a/src/java/com/android/internal/telephony/uicc/PlmnActRecord.java b/src/java/com/android/internal/telephony/uicc/PlmnActRecord.java
new file mode 100644
index 000000000..a4cf7cc1c
--- /dev/null
+++ b/src/java/com/android/internal/telephony/uicc/PlmnActRecord.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2006 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.uicc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.Rlog;
+
+import java.util.Arrays;
+
+/**
+ * {@hide}
+ */
+public class PlmnActRecord implements Parcelable {
+ private static final String LOG_TAG = "PlmnActRecord";
+
+ // Values specified in 3GPP 31.102 sec. 4.2.5
+ public static final int ACCESS_TECH_UTRAN = 0x8000;
+ public static final int ACCESS_TECH_EUTRAN = 0x4000;
+ public static final int ACCESS_TECH_GSM = 0x0080;
+ public static final int ACCESS_TECH_GSM_COMPACT = 0x0040;
+ public static final int ACCESS_TECH_CDMA2000_HRPD = 0x0020;
+ public static final int ACCESS_TECH_CDMA2000_1XRTT = 0x0010;
+ public static final int ACCESS_TECH_RESERVED = 0x3F0F;
+
+ public static final int ENCODED_LENGTH = 5;
+
+ public final String plmn;
+ public final int accessTechs;
+
+ private static final boolean VDBG = true;
+
+ public static final Parcelable.Creator<PlmnActRecord> CREATOR =
+ new Parcelable.Creator<PlmnActRecord>() {
+ @Override
+ public PlmnActRecord createFromParcel(Parcel source) {
+ return new PlmnActRecord(source.readString(), source.readInt());
+ }
+
+ @Override
+ public PlmnActRecord[] newArray(int size) {
+ return new PlmnActRecord[size];
+ }
+ };
+
+ /* From 3gpp 31.102 section 4.2.5
+ * Bytes 0-2 bcd-encoded PLMN-ID
+ * Bytes 3-4 bitfield of access technologies
+ */
+ public PlmnActRecord(byte[] bytes, int offset) {
+ if (VDBG) Rlog.v(LOG_TAG, "Creating PlmnActRecord " + offset);
+ this.plmn = IccUtils.bcdPlmnToString(bytes, offset);
+ this.accessTechs = ((int) bytes[offset + 3] << 8) | bytes[offset + 4];
+ }
+
+ private PlmnActRecord(String plmn, int accessTechs) {
+ this.plmn = plmn;
+ this.accessTechs = accessTechs;
+ }
+
+ private String accessTechString() {
+ if (accessTechs == 0) {
+ return "NONE";
+ }
+
+ StringBuilder sb = new StringBuilder();
+ if ((accessTechs & ACCESS_TECH_UTRAN) != 0) {
+ sb.append("UTRAN|");
+ }
+ if ((accessTechs & ACCESS_TECH_EUTRAN) != 0) {
+ sb.append("EUTRAN|");
+ }
+ if ((accessTechs & ACCESS_TECH_GSM) != 0) {
+ sb.append("GSM|");
+ }
+ if ((accessTechs & ACCESS_TECH_GSM_COMPACT) != 0) {
+ sb.append("GSM_COMPACT|");
+ }
+ if ((accessTechs & ACCESS_TECH_CDMA2000_HRPD) != 0) {
+ sb.append("CDMA2000_HRPD|");
+ }
+ if ((accessTechs & ACCESS_TECH_CDMA2000_1XRTT) != 0) {
+ sb.append("CDMA2000_1XRTT|");
+ }
+ if ((accessTechs & ACCESS_TECH_RESERVED) != 0) {
+ sb.append(String.format("UNKNOWN:%x|", accessTechs & ACCESS_TECH_RESERVED));
+ }
+ // Trim the tailing pipe character
+ return sb.substring(0, sb.length() - 1);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{PLMN=%s,AccessTechs=%s}", plmn, accessTechString());
+ }
+
+ /**
+ * Convenience method for extracting all records from encoded bytes
+ */
+ public static PlmnActRecord[] getRecords(byte[] recordBytes) {
+ if (recordBytes == null || recordBytes.length == 0
+ || recordBytes.length % ENCODED_LENGTH != 0) {
+ Rlog.e(LOG_TAG, "Malformed PlmnActRecord, bytes: "
+ + ((recordBytes != null) ? Arrays.toString(recordBytes) : null));
+ return null;
+ }
+ int numRecords = recordBytes.length / ENCODED_LENGTH;
+ if (VDBG) Rlog.v(LOG_TAG, "Extracting Logs, count=" + numRecords);
+
+ PlmnActRecord[] records = new PlmnActRecord[numRecords];
+
+ for(int i = 0; i < numRecords; i++) {
+ records[i] = new PlmnActRecord(recordBytes, i * ENCODED_LENGTH);
+ }
+ return records;
+ }
+
+ // Parcelable Implementation
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(plmn);
+ dest.writeInt(accessTechs);
+ }
+
+}
diff --git a/src/java/com/android/internal/telephony/uicc/SIMFileHandler.java b/src/java/com/android/internal/telephony/uicc/SIMFileHandler.java
index 8412b4eae..3be0c9914 100644
--- a/src/java/com/android/internal/telephony/uicc/SIMFileHandler.java
+++ b/src/java/com/android/internal/telephony/uicc/SIMFileHandler.java
@@ -56,8 +56,6 @@ public final class SIMFileHandler extends IccFileHandler implements IccConstants
case EF_CFIS:
case EF_GID1:
case EF_GID2:
- return MF_SIM + DF_GSM;
-
case EF_MAILBOX_CPHS:
case EF_VOICE_MAIL_INDICATOR_CPHS:
case EF_CFF_CPHS:
diff --git a/src/java/com/android/internal/telephony/uicc/SIMRecords.java b/src/java/com/android/internal/telephony/uicc/SIMRecords.java
index e936d85cf..96311b382 100644
--- a/src/java/com/android/internal/telephony/uicc/SIMRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/SIMRecords.java
@@ -20,15 +20,15 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Resources;
import android.os.AsyncResult;
import android.os.Message;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneNumberUtils;
+import android.telephony.Rlog;
import android.telephony.SmsMessage;
import android.telephony.SubscriptionInfo;
import android.text.TextUtils;
-import android.telephony.Rlog;
-import android.content.res.Resources;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.MccTable;
@@ -51,6 +51,8 @@ public class SIMRecords extends IccRecords {
private static final boolean CRASH_RIL = false;
+ private static final boolean VDBG = false;
+
// ***** Instance Variables
VoiceMailConstants mVmConfig;
@@ -138,36 +140,47 @@ public class SIMRecords extends IccRecords {
private static final int CFIS_ADN_EXTENSION_ID_OFFSET = 15;
// ***** Event Constants
- private static final int EVENT_GET_IMSI_DONE = 3;
- private 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;
- protected static final int EVENT_GET_AD_DONE = 9; // Admin data on SIM
- protected 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;
- private static final int EVENT_GET_SPDI_DONE = 13;
- private static final int EVENT_UPDATE_DONE = 14;
- private static final int EVENT_GET_PNN_DONE = 15;
- protected static final int EVENT_GET_SST_DONE = 17;
- private static final int EVENT_GET_ALL_SMS_DONE = 18;
- private static final int EVENT_MARK_SMS_READ_DONE = 19;
- private static final int EVENT_SET_MBDN_DONE = 20;
- private static final int EVENT_SMS_ON_SIM = 21;
- private static final int EVENT_GET_SMS_DONE = 22;
- private static final int EVENT_GET_CFF_DONE = 24;
- private static final int EVENT_SET_CPHS_MAILBOX_DONE = 25;
- private static final int EVENT_GET_INFO_CPHS_DONE = 26;
- // private static final int EVENT_SET_MSISDN_DONE = 30; Defined in IccRecords as 30
- private static final int EVENT_SIM_REFRESH = 31;
- private static final int EVENT_GET_CFIS_DONE = 32;
- private static final int EVENT_GET_CSP_CPHS_DONE = 33;
- private static final int EVENT_GET_GID1_DONE = 34;
- private static final int EVENT_APP_LOCKED = 35;
- private static final int EVENT_GET_GID2_DONE = 36;
- private static final int EVENT_CARRIER_CONFIG_CHANGED = 37;
+ private static final int SIM_RECORD_EVENT_BASE = 0x00;
+ private static final int EVENT_GET_IMSI_DONE = 3 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_ICCID_DONE = 4 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_MBI_DONE = 5 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_MBDN_DONE = 6 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_MWIS_DONE = 7 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE = 8 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_AD_DONE = 9 + SIM_RECORD_EVENT_BASE; // Admin data on SIM
+ private static final int EVENT_GET_MSISDN_DONE = 10 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_CPHS_MAILBOX_DONE = 11 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_SPN_DONE = 12 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_SPDI_DONE = 13 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_UPDATE_DONE = 14 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_PNN_DONE = 15 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_SST_DONE = 17 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_ALL_SMS_DONE = 18 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_MARK_SMS_READ_DONE = 19 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_SET_MBDN_DONE = 20 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_SMS_ON_SIM = 21 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_SMS_DONE = 22 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_CFF_DONE = 24 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_SET_CPHS_MAILBOX_DONE = 25 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_INFO_CPHS_DONE = 26 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_SET_MSISDN_DONE = 30 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_CFIS_DONE = 32 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_CSP_CPHS_DONE = 33 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_GID1_DONE = 34 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_GID2_DONE = 36 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_PLMN_W_ACT_DONE = 37 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_OPLMN_W_ACT_DONE = 38 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_HPLMN_W_ACT_DONE = 39 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_EHPLMN_DONE = 40 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_FPLMN_DONE = 41 + SIM_RECORD_EVENT_BASE;
+
+ // TODO: Possibly move these to IccRecords.java
+ private static final int SYSTEM_EVENT_BASE = 0x100;
+ private static final int EVENT_CARRIER_CONFIG_CHANGED = 1 + SYSTEM_EVENT_BASE;
+ private static final int EVENT_APP_LOCKED = 2 + SYSTEM_EVENT_BASE;
+ private static final int EVENT_SIM_REFRESH = 3 + SYSTEM_EVENT_BASE;
+
+
// Lookup table for carriers known to produce SIMs which incorrectly indicate MNC length.
@@ -262,6 +275,11 @@ public class SIMRecords extends IccRecords {
mPnnHomeName = null;
mGid1 = null;
mGid2 = null;
+ mPlmnActRecords = null;
+ mOplmnActRecords = null;
+ mHplmnActRecords = null;
+ mFplmns = null;
+ mEhplmns = null;
mAdnCache.reset();
@@ -1240,6 +1258,76 @@ public class SIMRecords extends IccRecords {
break;
+ case EVENT_GET_PLMN_W_ACT_DONE:
+ isRecordLoadResponse = true;
+ ar = (AsyncResult) msg.obj;
+ data = (byte[]) ar.result;
+
+ if (ar.exception != null || data == null) {
+ loge("Failed getting User PLMN with Access Tech Records: " + ar.exception);
+ break;
+ } else {
+ log("Received a PlmnActRecord, raw=" + IccUtils.bytesToHexString(data));
+ mPlmnActRecords = PlmnActRecord.getRecords(data);
+ if (VDBG) log("PlmnActRecords=" + Arrays.toString(mPlmnActRecords));
+ }
+ break;
+
+ case EVENT_GET_OPLMN_W_ACT_DONE:
+ isRecordLoadResponse = true;
+ ar = (AsyncResult) msg.obj;
+ data = (byte[]) ar.result;
+
+ if (ar.exception != null || data == null) {
+ loge("Failed getting Operator PLMN with Access Tech Records: "
+ + ar.exception);
+ break;
+ } else {
+ log("Received a PlmnActRecord, raw=" + IccUtils.bytesToHexString(data));
+ mOplmnActRecords = PlmnActRecord.getRecords(data);
+ if (VDBG) log("OplmnActRecord[]=" + Arrays.toString(mOplmnActRecords));
+ }
+ break;
+
+ case EVENT_GET_HPLMN_W_ACT_DONE:
+ isRecordLoadResponse = true;
+ ar = (AsyncResult) msg.obj;
+ data = (byte[]) ar.result;
+
+ if (ar.exception != null || data == null) {
+ loge("Failed getting Home PLMN with Access Tech Records: " + ar.exception);
+ break;
+ } else {
+ log("Received a PlmnActRecord, raw=" + IccUtils.bytesToHexString(data));
+ mHplmnActRecords = PlmnActRecord.getRecords(data);
+ log("HplmnActRecord[]=" + Arrays.toString(mHplmnActRecords));
+ }
+ break;
+
+ case EVENT_GET_EHPLMN_DONE:
+ isRecordLoadResponse = true;
+ ar = (AsyncResult) msg.obj;
+ data = (byte[]) ar.result;
+ if (ar.exception != null || data == null) {
+ loge("Failed getting Equivalent Home PLMNs: " + ar.exception);
+ break;
+ } else {
+ mEhplmns = parseBcdPlmnList(data, "Equivalent Home");
+ }
+ break;
+
+ case EVENT_GET_FPLMN_DONE:
+ isRecordLoadResponse = true;
+ ar = (AsyncResult) msg.obj;
+ data = (byte[]) ar.result;
+ if (ar.exception != null || data == null) {
+ loge("Failed getting Forbidden PLMNs: " + ar.exception);
+ break;
+ } else {
+ mFplmns = parseBcdPlmnList(data, "Forbidden");
+ }
+ break;
+
case EVENT_CARRIER_CONFIG_CHANGED:
handleCarrierNameOverride();
break;
@@ -1634,6 +1722,21 @@ public class SIMRecords extends IccRecords {
mFh.loadEFTransparent(EF_GID2, obtainMessage(EVENT_GET_GID2_DONE));
mRecordsToLoad++;
+ mFh.loadEFTransparent(EF_PLMN_W_ACT, obtainMessage(EVENT_GET_PLMN_W_ACT_DONE));
+ mRecordsToLoad++;
+
+ mFh.loadEFTransparent(EF_OPLMN_W_ACT, obtainMessage(EVENT_GET_OPLMN_W_ACT_DONE));
+ mRecordsToLoad++;
+
+ mFh.loadEFTransparent(EF_HPLMN_W_ACT, obtainMessage(EVENT_GET_HPLMN_W_ACT_DONE));
+ mRecordsToLoad++;
+
+ mFh.loadEFTransparent(EF_EHPLMN, obtainMessage(EVENT_GET_EHPLMN_DONE));
+ mRecordsToLoad++;
+
+ mFh.loadEFTransparent(EF_FPLMN, obtainMessage(EVENT_GET_FPLMN_DONE));
+ mRecordsToLoad++;
+
loadEfLiAndEfPl();
// XXX should seek instead of examining them all
@@ -1910,6 +2013,25 @@ public class SIMRecords extends IccRecords {
}
/**
+ * convert a byte array of packed plmns to an array of strings
+ */
+ private String[] parseBcdPlmnList(byte[] data, String description) {
+ final int packedBcdPlmnLenBytes = 3;
+ log("Received " + description + " PLMNs, raw=" + IccUtils.bytesToHexString(data));
+ if (data.length == 0 || (data.length % packedBcdPlmnLenBytes) != 0) {
+ loge("Received invalid " + description + " PLMN list");
+ return null;
+ }
+ int numPlmns = data.length / packedBcdPlmnLenBytes;
+ String[] ret = new String[numPlmns];
+ for (int i = 0; i < numPlmns; i++) {
+ ret[i] = IccUtils.bcdPlmnToString(data, i * packedBcdPlmnLenBytes);
+ }
+ if (VDBG) logv(description + " PLMNs: " + Arrays.toString(ret));
+ return ret;
+ }
+
+ /**
* check to see if Mailbox Number is allocated and activated in CPHS SST
*/
private boolean isCphsMailboxEnabled() {
@@ -2006,6 +2128,11 @@ public class SIMRecords extends IccRecords {
pw.println(" mUsimServiceTable=" + mUsimServiceTable);
pw.println(" mGid1=" + mGid1);
pw.println(" mGid2=" + mGid2);
+ pw.println(" mPlmnActRecords[]=" + Arrays.toString(mPlmnActRecords));
+ pw.println(" mOplmnActRecords[]=" + Arrays.toString(mOplmnActRecords));
+ pw.println(" mHplmnActRecords[]=" + Arrays.toString(mHplmnActRecords));
+ pw.println(" mFplmns[]=" + Arrays.toString(mFplmns));
+ pw.println(" mEhplmns[]=" + Arrays.toString(mEhplmns));
pw.flush();
}
}
diff --git a/src/java/com/android/internal/telephony/uicc/UsimFileHandler.java b/src/java/com/android/internal/telephony/uicc/UsimFileHandler.java
index bd3357ee6..f2834f7ec 100644
--- a/src/java/com/android/internal/telephony/uicc/UsimFileHandler.java
+++ b/src/java/com/android/internal/telephony/uicc/UsimFileHandler.java
@@ -61,6 +61,13 @@ public final class UsimFileHandler extends IccFileHandler implements IccConstant
case EF_GID1:
case EF_GID2:
case EF_LI:
+ case EF_PLMN_W_ACT:
+ case EF_OPLMN_W_ACT:
+ case EF_HPLMN_W_ACT:
+ case EF_EHPLMN:
+ case EF_FPLMN:
+ case EF_LRPLMNSI:
+ case EF_HPPLMN:
return MF_SIM + DF_ADF;
case EF_PBR: