Loading src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java +73 −12 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import java.io.ByteArrayInputStream; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.IllegalArgumentException; import java.lang.IndexOutOfBoundsException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.cert.Certificate; Loading Loading @@ -72,6 +73,7 @@ public class UiccCarrierPrivilegeRules extends Handler { private static final int COMMAND = 0xCA; private static final int P1 = 0xFF; private static final int P2 = 0x40; private static final int P2_EXTENDED_DATA = 0x60; private static final int P3 = 0x00; private static final String DATA = ""; Loading Loading @@ -140,7 +142,14 @@ public class UiccCarrierPrivilegeRules extends Handler { // Used for parsing the data from the UICC. private static class TLV { private static final int SINGLE_BYTE_MAX_LENGTH = 0x80; private String tag; // Length encoding is in GPC_Specification_2.2.1: 11.1.5 APDU Message and Data Length. // Length field could be either 1 byte if length < 128, or multiple bytes with first byte // specifying how many bytes are used for length, followed by length bytes. // Bytes for the length field, in ASCII HEX string form. private String lengthBytes; // Decoded length as integer. private Integer length; private String value; Loading @@ -148,6 +157,22 @@ public class UiccCarrierPrivilegeRules extends Handler { this.tag = tag; } public String parseLength(String data) { int offset = tag.length(); int firstByte = Integer.parseInt(data.substring(offset, offset + 2), 16); // TODO: remove second condition before launch. b/18012893 if (firstByte < SINGLE_BYTE_MAX_LENGTH || (offset + 2 + firstByte * 2 == data.length())) { length = firstByte * 2; lengthBytes = data.substring(offset, offset + 2); } else { int numBytes = firstByte - SINGLE_BYTE_MAX_LENGTH; length = Integer.parseInt(data.substring(offset + 2, offset + 2 + numBytes * 2), 16) * 2; lengthBytes = data.substring(offset, offset + 2 + numBytes * 2); } Rlog.d(LOG_TAG, "TLV parseLength length=" + length + "lenghtBytes: " + lengthBytes); return lengthBytes; } public String parse(String data, boolean shouldConsumeAll) { Rlog.d(LOG_TAG, "Parse TLV: " + tag); if (!data.startsWith(tag)) { Loading @@ -157,10 +182,11 @@ public class UiccCarrierPrivilegeRules extends Handler { if (index + 2 > data.length()) { throw new IllegalArgumentException("No length."); } length = new Integer(2 * Integer.parseInt( data.substring(index, index + 2), 16)); index += 2; parseLength(data); index += lengthBytes.length(); Rlog.d(LOG_TAG, "index="+index+" length="+length+"data.length="+data.length()); int remainingLength = data.length() - (index + length); if (remainingLength < 0) { throw new IllegalArgumentException("Not enough data."); Loading @@ -179,8 +205,10 @@ public class UiccCarrierPrivilegeRules extends Handler { private UiccCard mUiccCard; // Parent private AtomicInteger mState; private List<AccessRule> mAccessRules; private String mRules; private Message mLoadedCallback; private String mStatusMessage; // Only used for debugging. private int mChannelId; // Channel Id for communicating with UICC. public UiccCarrierPrivilegeRules(UiccCard uiccCard, Message loadedCallback) { Rlog.d(LOG_TAG, "Creating UiccCarrierPrivilegeRules"); Loading @@ -188,6 +216,7 @@ public class UiccCarrierPrivilegeRules extends Handler { mState = new AtomicInteger(STATE_LOADING); mStatusMessage = "Not loaded."; mLoadedCallback = loadedCallback; mRules = ""; // Start loading the rules. mUiccCard.iccOpenLogicalChannel(AID, Loading Loading @@ -322,9 +351,9 @@ public class UiccCarrierPrivilegeRules extends Handler { Rlog.d(LOG_TAG, "EVENT_OPEN_LOGICAL_CHANNEL_DONE"); ar = (AsyncResult) msg.obj; if (ar.exception == null && ar.result != null) { int channelId = ((int[]) ar.result)[0]; mUiccCard.iccTransmitApduLogicalChannel(channelId, CLA, COMMAND, P1, P2, P3, DATA, obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, new Integer(channelId))); mChannelId = ((int[]) ar.result)[0]; mUiccCard.iccTransmitApduLogicalChannel(mChannelId, CLA, COMMAND, P1, P2, P3, DATA, obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, new Integer(mChannelId))); } else { updateState(STATE_ERROR, "Error opening channel"); } Loading @@ -335,12 +364,22 @@ public class UiccCarrierPrivilegeRules extends Handler { ar = (AsyncResult) msg.obj; if (ar.exception == null && ar.result != null) { IccIoResult response = (IccIoResult) ar.result; if (response.payload != null && response.sw1 == 0x90 && response.sw2 == 0x00) { if (response.sw1 == 0x90 && response.sw2 == 0x00 && response.payload != null && response.payload.length > 0) { try { mAccessRules = parseRules(IccUtils.bytesToHexString(response.payload)); updateState(STATE_LOADED, "Loaded successfully"); mRules += IccUtils.bytesToHexString(response.payload).toUpperCase(Locale.US); if (isDataComplete()) { mAccessRules = parseRules(mRules); updateState(STATE_LOADED, "Success!"); } else { mUiccCard.iccTransmitApduLogicalChannel(mChannelId, CLA, COMMAND, P1, P2_EXTENDED_DATA, P3, DATA, obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, new Integer(mChannelId))); break; } } catch (IllegalArgumentException ex) { updateState(STATE_ERROR, "Error parsing rules: " + ex); } catch (IndexOutOfBoundsException ex) { updateState(STATE_ERROR, "Error parsing rules: " + ex); } } else { String errorMsg = "Invalid response: payload=" + response.payload + Loading @@ -351,9 +390,9 @@ public class UiccCarrierPrivilegeRules extends Handler { updateState(STATE_ERROR, "Error reading value from SIM."); } int channelId = (Integer) ar.userObj; mUiccCard.iccCloseLogicalChannel(channelId, obtainMessage( mUiccCard.iccCloseLogicalChannel(mChannelId, obtainMessage( EVENT_CLOSE_LOGICAL_CHANNEL_DONE)); mChannelId = -1; break; case EVENT_CLOSE_LOGICAL_CHANNEL_DONE: Loading @@ -365,11 +404,33 @@ public class UiccCarrierPrivilegeRules extends Handler { } } /* * Check if all rule bytes have been read from UICC. * For long payload, we need to fetch it repeatly before start parsing it. */ private boolean isDataComplete() { Rlog.d(LOG_TAG, "isDataComplete mRules:" + mRules); if (mRules.startsWith(TAG_ALL_REF_AR_DO)) { TLV allRules = new TLV(TAG_ALL_REF_AR_DO); String lengthBytes = allRules.parseLength(mRules); Rlog.d(LOG_TAG, "isDataComplete lengthBytes: " + lengthBytes); if (mRules.length() == TAG_ALL_REF_AR_DO.length() + lengthBytes.length() + allRules.length) { Rlog.d(LOG_TAG, "isDataComplete yes"); return true; } else { Rlog.d(LOG_TAG, "isDataComplete no"); return false; } } else { throw new IllegalArgumentException("Tags don't match."); } } /* * Parses the rules from the input string. */ private static List<AccessRule> parseRules(String rules) { rules = rules.toUpperCase(Locale.US); Rlog.d(LOG_TAG, "Got rules: " + rules); TLV allRefArDo = new TLV(TAG_ALL_REF_AR_DO); //FF40 Loading Loading
src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java +73 −12 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import java.io.ByteArrayInputStream; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.IllegalArgumentException; import java.lang.IndexOutOfBoundsException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.cert.Certificate; Loading Loading @@ -72,6 +73,7 @@ public class UiccCarrierPrivilegeRules extends Handler { private static final int COMMAND = 0xCA; private static final int P1 = 0xFF; private static final int P2 = 0x40; private static final int P2_EXTENDED_DATA = 0x60; private static final int P3 = 0x00; private static final String DATA = ""; Loading Loading @@ -140,7 +142,14 @@ public class UiccCarrierPrivilegeRules extends Handler { // Used for parsing the data from the UICC. private static class TLV { private static final int SINGLE_BYTE_MAX_LENGTH = 0x80; private String tag; // Length encoding is in GPC_Specification_2.2.1: 11.1.5 APDU Message and Data Length. // Length field could be either 1 byte if length < 128, or multiple bytes with first byte // specifying how many bytes are used for length, followed by length bytes. // Bytes for the length field, in ASCII HEX string form. private String lengthBytes; // Decoded length as integer. private Integer length; private String value; Loading @@ -148,6 +157,22 @@ public class UiccCarrierPrivilegeRules extends Handler { this.tag = tag; } public String parseLength(String data) { int offset = tag.length(); int firstByte = Integer.parseInt(data.substring(offset, offset + 2), 16); // TODO: remove second condition before launch. b/18012893 if (firstByte < SINGLE_BYTE_MAX_LENGTH || (offset + 2 + firstByte * 2 == data.length())) { length = firstByte * 2; lengthBytes = data.substring(offset, offset + 2); } else { int numBytes = firstByte - SINGLE_BYTE_MAX_LENGTH; length = Integer.parseInt(data.substring(offset + 2, offset + 2 + numBytes * 2), 16) * 2; lengthBytes = data.substring(offset, offset + 2 + numBytes * 2); } Rlog.d(LOG_TAG, "TLV parseLength length=" + length + "lenghtBytes: " + lengthBytes); return lengthBytes; } public String parse(String data, boolean shouldConsumeAll) { Rlog.d(LOG_TAG, "Parse TLV: " + tag); if (!data.startsWith(tag)) { Loading @@ -157,10 +182,11 @@ public class UiccCarrierPrivilegeRules extends Handler { if (index + 2 > data.length()) { throw new IllegalArgumentException("No length."); } length = new Integer(2 * Integer.parseInt( data.substring(index, index + 2), 16)); index += 2; parseLength(data); index += lengthBytes.length(); Rlog.d(LOG_TAG, "index="+index+" length="+length+"data.length="+data.length()); int remainingLength = data.length() - (index + length); if (remainingLength < 0) { throw new IllegalArgumentException("Not enough data."); Loading @@ -179,8 +205,10 @@ public class UiccCarrierPrivilegeRules extends Handler { private UiccCard mUiccCard; // Parent private AtomicInteger mState; private List<AccessRule> mAccessRules; private String mRules; private Message mLoadedCallback; private String mStatusMessage; // Only used for debugging. private int mChannelId; // Channel Id for communicating with UICC. public UiccCarrierPrivilegeRules(UiccCard uiccCard, Message loadedCallback) { Rlog.d(LOG_TAG, "Creating UiccCarrierPrivilegeRules"); Loading @@ -188,6 +216,7 @@ public class UiccCarrierPrivilegeRules extends Handler { mState = new AtomicInteger(STATE_LOADING); mStatusMessage = "Not loaded."; mLoadedCallback = loadedCallback; mRules = ""; // Start loading the rules. mUiccCard.iccOpenLogicalChannel(AID, Loading Loading @@ -322,9 +351,9 @@ public class UiccCarrierPrivilegeRules extends Handler { Rlog.d(LOG_TAG, "EVENT_OPEN_LOGICAL_CHANNEL_DONE"); ar = (AsyncResult) msg.obj; if (ar.exception == null && ar.result != null) { int channelId = ((int[]) ar.result)[0]; mUiccCard.iccTransmitApduLogicalChannel(channelId, CLA, COMMAND, P1, P2, P3, DATA, obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, new Integer(channelId))); mChannelId = ((int[]) ar.result)[0]; mUiccCard.iccTransmitApduLogicalChannel(mChannelId, CLA, COMMAND, P1, P2, P3, DATA, obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, new Integer(mChannelId))); } else { updateState(STATE_ERROR, "Error opening channel"); } Loading @@ -335,12 +364,22 @@ public class UiccCarrierPrivilegeRules extends Handler { ar = (AsyncResult) msg.obj; if (ar.exception == null && ar.result != null) { IccIoResult response = (IccIoResult) ar.result; if (response.payload != null && response.sw1 == 0x90 && response.sw2 == 0x00) { if (response.sw1 == 0x90 && response.sw2 == 0x00 && response.payload != null && response.payload.length > 0) { try { mAccessRules = parseRules(IccUtils.bytesToHexString(response.payload)); updateState(STATE_LOADED, "Loaded successfully"); mRules += IccUtils.bytesToHexString(response.payload).toUpperCase(Locale.US); if (isDataComplete()) { mAccessRules = parseRules(mRules); updateState(STATE_LOADED, "Success!"); } else { mUiccCard.iccTransmitApduLogicalChannel(mChannelId, CLA, COMMAND, P1, P2_EXTENDED_DATA, P3, DATA, obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, new Integer(mChannelId))); break; } } catch (IllegalArgumentException ex) { updateState(STATE_ERROR, "Error parsing rules: " + ex); } catch (IndexOutOfBoundsException ex) { updateState(STATE_ERROR, "Error parsing rules: " + ex); } } else { String errorMsg = "Invalid response: payload=" + response.payload + Loading @@ -351,9 +390,9 @@ public class UiccCarrierPrivilegeRules extends Handler { updateState(STATE_ERROR, "Error reading value from SIM."); } int channelId = (Integer) ar.userObj; mUiccCard.iccCloseLogicalChannel(channelId, obtainMessage( mUiccCard.iccCloseLogicalChannel(mChannelId, obtainMessage( EVENT_CLOSE_LOGICAL_CHANNEL_DONE)); mChannelId = -1; break; case EVENT_CLOSE_LOGICAL_CHANNEL_DONE: Loading @@ -365,11 +404,33 @@ public class UiccCarrierPrivilegeRules extends Handler { } } /* * Check if all rule bytes have been read from UICC. * For long payload, we need to fetch it repeatly before start parsing it. */ private boolean isDataComplete() { Rlog.d(LOG_TAG, "isDataComplete mRules:" + mRules); if (mRules.startsWith(TAG_ALL_REF_AR_DO)) { TLV allRules = new TLV(TAG_ALL_REF_AR_DO); String lengthBytes = allRules.parseLength(mRules); Rlog.d(LOG_TAG, "isDataComplete lengthBytes: " + lengthBytes); if (mRules.length() == TAG_ALL_REF_AR_DO.length() + lengthBytes.length() + allRules.length) { Rlog.d(LOG_TAG, "isDataComplete yes"); return true; } else { Rlog.d(LOG_TAG, "isDataComplete no"); return false; } } else { throw new IllegalArgumentException("Tags don't match."); } } /* * Parses the rules from the input string. */ private static List<AccessRule> parseRules(String rules) { rules = rules.toUpperCase(Locale.US); Rlog.d(LOG_TAG, "Got rules: " + rules); TLV allRefArDo = new TLV(TAG_ALL_REF_AR_DO); //FF40 Loading