1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony.cat; 18 19 import java.util.ArrayList; 20 import java.util.List; 21 22 23 /** 24 * Class for representing COMPREHENSION-TLV objects. 25 * 26 * @see "ETSI TS 101 220 subsection 7.1.1" 27 * 28 * {@hide} 29 */ 30 class ComprehensionTlv { 31 private static final String LOG_TAG = "ComprehensionTlv"; 32 private int mTag; 33 private boolean mCr; 34 private int mLength; 35 private int mValueIndex; 36 private byte[] mRawValue; 37 38 /** 39 * Constructor. Private on purpose. Use 40 * {@link #decodeMany(byte[], int) decodeMany} or 41 * {@link #decode(byte[], int) decode} method. 42 * 43 * @param tag The tag for this object 44 * @param cr Comprehension Required flag 45 * @param length Length of the value 46 * @param data Byte array containing the value 47 * @param valueIndex Index in data at which the value starts 48 */ 49 protected ComprehensionTlv(int tag, boolean cr, int length, byte[] data, 50 int valueIndex) { 51 mTag = tag; 52 mCr = cr; 53 mLength = length; 54 mValueIndex = valueIndex; 55 mRawValue = data; 56 } 57 58 public int getTag() { 59 return mTag; 60 } 61 62 public boolean isComprehensionRequired() { 63 return mCr; 64 } 65 66 public int getLength() { 67 return mLength; 68 } 69 70 public int getValueIndex() { 71 return mValueIndex; 72 } 73 74 public byte[] getRawValue() { 75 return mRawValue; 76 } 77 78 /** 79 * Parses a list of COMPREHENSION-TLV objects from a byte array. 80 * 81 * @param data A byte array containing data to be parsed 82 * @param startIndex Index in data at which to start parsing 83 * @return A list of COMPREHENSION-TLV objects parsed 84 * @throws ResultException 85 */ 86 public static List<ComprehensionTlv> decodeMany(byte[] data, int startIndex) 87 throws ResultException { 88 ArrayList<ComprehensionTlv> items = new ArrayList<ComprehensionTlv>(); 89 int endIndex = data.length; 90 while (startIndex < endIndex) { 91 ComprehensionTlv ctlv = ComprehensionTlv.decode(data, startIndex); 92 if (ctlv != null) { 93 items.add(ctlv); 94 startIndex = ctlv.mValueIndex + ctlv.mLength; 95 } else { 96 CatLog.d(LOG_TAG, "decodeMany: ctlv is null, stop decoding"); 97 items.clear(); 98 break; 99 } 100 } 101 102 return items; 103 } 104 105 /** 106 * Parses an COMPREHENSION-TLV object from a byte array. 107 * 108 * @param data A byte array containing data to be parsed 109 * @param startIndex Index in data at which to start parsing 110 * @return A COMPREHENSION-TLV object parsed 111 * @throws ResultException 112 */ 113 public static ComprehensionTlv decode(byte[] data, int startIndex) 114 throws ResultException { 115 try { 116 int curIndex = startIndex; 117 int endIndex = data.length; 118 119 /* tag */ 120 int tag; 121 boolean cr; // Comprehension required flag 122 int temp = data[curIndex++] & 0xff; 123 switch (temp) { 124 case 0: 125 case 0xff: 126 case 0x80: 127 // for error handling 128 // these one make exception while decoding the abnormal command. 129 // (in case of Ghana MTN simcard , JDI simcard) 130 return null; 131 132 case 0x7f: // tag is in three-byte format 133 tag = ((data[curIndex] & 0xff) << 8) 134 | (data[curIndex + 1] & 0xff); 135 cr = (tag & 0x8000) != 0; 136 tag &= ~0x8000; 137 curIndex += 2; 138 break; 139 140 default: // tag is in single-byte format 141 tag = temp; 142 cr = (tag & 0x80) != 0; 143 tag &= ~0x80; 144 break; 145 } 146 147 /* length */ 148 int length; 149 temp = data[curIndex++] & 0xff; 150 if (temp < 0x80) { 151 length = temp; 152 } else if (temp == 0x81) { 153 length = data[curIndex++] & 0xff; 154 if (length < 0x80) { 155 throw new ResultException( 156 ResultCode.CMD_DATA_NOT_UNDERSTOOD); 157 } 158 } else if (temp == 0x82) { 159 length = ((data[curIndex] & 0xff) << 8) 160 | (data[curIndex + 1] & 0xff); 161 curIndex += 2; 162 if (length < 0x100) { 163 throw new ResultException( 164 ResultCode.CMD_DATA_NOT_UNDERSTOOD); 165 } 166 } else if (temp == 0x83) { 167 length = ((data[curIndex] & 0xff) << 16) 168 | ((data[curIndex + 1] & 0xff) << 8) 169 | (data[curIndex + 2] & 0xff); 170 curIndex += 3; 171 if (length < 0x10000) { 172 throw new ResultException( 173 ResultCode.CMD_DATA_NOT_UNDERSTOOD); 174 } 175 } else { 176 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 177 } 178 179 return new ComprehensionTlv(tag, cr, length, data, curIndex); 180 181 } catch (IndexOutOfBoundsException e) { 182 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 183 } 184 } 185 } 186