aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Harold <nharold@google.com>2016-10-31 16:27:34 -0700
committerNathan Harold <nharold@google.com>2016-12-05 15:20:06 -0800
commit229d3318ca022dcda540a86b9f60bb314c78998b (patch)
tree97c9186cd6913300364d0a3a444eb8950fd8ae3a
parent4a1959c22e94e69040b6cab21fa08ca2e1df0c9b (diff)
downloadandroid_frameworks_opt_telephony-229d3318ca022dcda540a86b9f60bb314c78998b.tar.gz
android_frameworks_opt_telephony-229d3318ca022dcda540a86b9f60bb314c78998b.tar.bz2
android_frameworks_opt_telephony-229d3318ca022dcda540a86b9f60bb314c78998b.zip
Add PLMN Selection Info to SIM Records
Pull new paramters from SIMs and add them to SIMRecords dumpsys for debugging purposes. -Add OPLMNw/ACT -Add HPLMNw/ACT -Add FPLMN -Add PLMNw/ACT Bug: 32277497 Test: none Change-Id: I28bd67e3667d5c6ba1046c43f24d8e02ce7b8313
-rw-r--r--src/java/com/android/internal/telephony/uicc/IccConstants.java15
-rw-r--r--src/java/com/android/internal/telephony/uicc/IccFileHandler.java8
-rw-r--r--src/java/com/android/internal/telephony/uicc/IccRecords.java7
-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/SIMRecords.java121
-rw-r--r--src/java/com/android/internal/telephony/uicc/UsimFileHandler.java7
7 files changed, 324 insertions, 1 deletions
diff --git a/src/java/com/android/internal/telephony/uicc/IccConstants.java b/src/java/com/android/internal/telephony/uicc/IccConstants.java
index 772516680..970bf358e 100644
--- a/src/java/com/android/internal/telephony/uicc/IccConstants.java
+++ b/src/java/com/android/internal/telephony/uicc/IccConstants.java
@@ -82,6 +82,21 @@ public interface IccConstants {
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;
// SMS record length from C.S0023 3.4.27
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/IccRecords.java b/src/java/com/android/internal/telephony/uicc/IccRecords.java
index 1c6fa9847..6bbecfe85 100644
--- a/src/java/com/android/internal/telephony/uicc/IccRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/IccRecords.java
@@ -89,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
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/SIMRecords.java b/src/java/com/android/internal/telephony/uicc/SIMRecords.java
index c06d7fbd0..96311b382 100644
--- a/src/java/com/android/internal/telephony/uicc/SIMRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/SIMRecords.java
@@ -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;
@@ -166,6 +168,11 @@ public class SIMRecords extends IccRecords {
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;
@@ -268,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();
@@ -1246,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;
@@ -1640,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
@@ -1916,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() {
@@ -2012,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: