10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/* 20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2011 The Android Open Source Project 30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License. 60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at 70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * http://www.apache.org/licenses/LICENSE-2.0 90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software 110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS, 120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and 140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License. 150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony.cat; 180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.Log; 200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList; 220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.List; 230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/** 260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Class for representing COMPREHENSION-TLV objects. 270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @see "ETSI TS 101 220 subsection 7.1.1" 290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * {@hide} 310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 320825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleclass ComprehensionTlv { 330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String LOG_TAG = "ComprehensionTlv"; 340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private int mTag; 350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean mCr; 360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private int mLength; 370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private int mValueIndex; 380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private byte[] mRawValue; 390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Constructor. Private on purpose. Use 420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * {@link #decodeMany(byte[], int) decodeMany} or 430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * {@link #decode(byte[], int) decode} method. 440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tag The tag for this object 460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param cr Comprehension Required flag 470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param length Length of the value 480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param data Byte array containing the value 490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param valueIndex Index in data at which the value starts 500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected ComprehensionTlv(int tag, boolean cr, int length, byte[] data, 520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int valueIndex) { 530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mTag = tag; 540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mCr = cr; 550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLength = length; 560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mValueIndex = valueIndex; 570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mRawValue = data; 580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int getTag() { 610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return mTag; 620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean isComprehensionRequired() { 650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return mCr; 660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int getLength() { 690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return mLength; 700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int getValueIndex() { 730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return mValueIndex; 740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public byte[] getRawValue() { 770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return mRawValue; 780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Parses a list of COMPREHENSION-TLV objects from a byte array. 820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param data A byte array containing data to be parsed 840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param startIndex Index in data at which to start parsing 850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return A list of COMPREHENSION-TLV objects parsed 860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @throws ResultException 870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static List<ComprehensionTlv> decodeMany(byte[] data, int startIndex) 890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws ResultException { 900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<ComprehensionTlv> items = new ArrayList<ComprehensionTlv>(); 910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int endIndex = data.length; 920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville while (startIndex < endIndex) { 930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ComprehensionTlv ctlv = ComprehensionTlv.decode(data, startIndex); 940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ctlv != null) { 950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville items.add(ctlv); 960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville startIndex = ctlv.mValueIndex + ctlv.mLength; 970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville CatLog.d(LOG_TAG, "decodeMany: ctlv is null, stop decoding"); 990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return items; 1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Parses an COMPREHENSION-TLV object from a byte array. 1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param data A byte array containing data to be parsed 1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param startIndex Index in data at which to start parsing 1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return A COMPREHENSION-TLV object parsed 1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @throws ResultException 1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static ComprehensionTlv decode(byte[] data, int startIndex) 1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws ResultException { 1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int curIndex = startIndex; 1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int endIndex = data.length; 1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* tag */ 1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int tag; 1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean cr; // Comprehension required flag 1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int temp = data[curIndex++] & 0xff; 1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (temp) { 1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 0: 1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 0xff: 1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 0x80: 1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Log.d("CAT ", "decode: unexpected first tag byte=" + Integer.toHexString(temp) + 1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ", startIndex=" + startIndex + " curIndex=" + curIndex + 1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " endIndex=" + endIndex); 1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Return null which will stop decoding, this has occurred 1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // with Ghana MTN simcard and JDI simcard. 1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return null; 1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 0x7f: // tag is in three-byte format 1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tag = ((data[curIndex] & 0xff) << 8) 1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville | (data[curIndex + 1] & 0xff); 1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville cr = (tag & 0x8000) != 0; 1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tag &= ~0x8000; 1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville curIndex += 2; 1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville default: // tag is in single-byte format 1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tag = temp; 1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville cr = (tag & 0x80) != 0; 1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tag &= ~0x80; 1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* length */ 1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int length; 1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville temp = data[curIndex++] & 0xff; 1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (temp < 0x80) { 1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville length = temp; 1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (temp == 0x81) { 1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville length = data[curIndex++] & 0xff; 1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (length < 0x80) { 1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new ResultException( 1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ResultCode.CMD_DATA_NOT_UNDERSTOOD, 1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "length < 0x80 length=" + Integer.toHexString(length) + 1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " startIndex=" + startIndex + " curIndex=" + curIndex + 1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " endIndex=" + endIndex); 1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (temp == 0x82) { 1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville length = ((data[curIndex] & 0xff) << 8) 1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville | (data[curIndex + 1] & 0xff); 1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville curIndex += 2; 1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (length < 0x100) { 1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new ResultException( 1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ResultCode.CMD_DATA_NOT_UNDERSTOOD, 1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "two byte length < 0x100 length=" + Integer.toHexString(length) + 1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " startIndex=" + startIndex + " curIndex=" + curIndex + 1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " endIndex=" + endIndex); 1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (temp == 0x83) { 1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville length = ((data[curIndex] & 0xff) << 16) 1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville | ((data[curIndex + 1] & 0xff) << 8) 1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville | (data[curIndex + 2] & 0xff); 1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville curIndex += 3; 1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (length < 0x10000) { 1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new ResultException( 1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ResultCode.CMD_DATA_NOT_UNDERSTOOD, 1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "three byte length < 0x10000 length=0x" + Integer.toHexString(length) + 1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " startIndex=" + startIndex + " curIndex=" + curIndex + 1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " endIndex=" + endIndex); 1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD, 1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "Bad length modifer=" + temp + 1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " startIndex=" + startIndex + " curIndex=" + curIndex + 1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " endIndex=" + endIndex); 1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return new ComprehensionTlv(tag, cr, length, data, curIndex); 1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (IndexOutOfBoundsException e) { 1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD, 1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "IndexOutOfBoundsException" + " startIndex=" + startIndex + 2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " curIndex=" + curIndex + " endIndex=" + endIndex); 2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville} 204