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 android.compat.annotation.UnsupportedAppUsage; 20 21 import com.android.telephony.Rlog; 22 23 import java.util.ArrayList; 24 import java.util.List; 25 26 /** 27 * Class for representing COMPREHENSION-TLV objects. 28 * 29 * @see "ETSI TS 101 220 subsection 7.1.1" 30 * 31 * {@hide} 32 */ 33 public class ComprehensionTlv { 34 private static final String LOG_TAG = "ComprehensionTlv"; 35 private int mTag; 36 private boolean mCr; 37 private int mLength; 38 private int mValueIndex; 39 private byte[] mRawValue; 40 41 /** 42 * Constructor. Private on purpose. Use 43 * {@link #decodeMany(byte[], int) decodeMany} or 44 * {@link #decode(byte[], int) decode} method. 45 * 46 * @param tag The tag for this object 47 * @param cr Comprehension Required flag 48 * @param length Length of the value 49 * @param data Byte array containing the value 50 * @param valueIndex Index in data at which the value starts 51 */ ComprehensionTlv(int tag, boolean cr, int length, byte[] data, int valueIndex)52 protected ComprehensionTlv(int tag, boolean cr, int length, byte[] data, 53 int valueIndex) { 54 mTag = tag; 55 mCr = cr; 56 mLength = length; 57 mValueIndex = valueIndex; 58 mRawValue = data; 59 } 60 61 @UnsupportedAppUsage getTag()62 public int getTag() { 63 return mTag; 64 } 65 isComprehensionRequired()66 public boolean isComprehensionRequired() { 67 return mCr; 68 } 69 70 @UnsupportedAppUsage getLength()71 public int getLength() { 72 return mLength; 73 } 74 75 @UnsupportedAppUsage getValueIndex()76 public int getValueIndex() { 77 return mValueIndex; 78 } 79 80 @UnsupportedAppUsage getRawValue()81 public byte[] getRawValue() { 82 return mRawValue; 83 } 84 85 /** 86 * Parses a list of COMPREHENSION-TLV objects from a byte array. 87 * 88 * @param data A byte array containing data to be parsed 89 * @param startIndex Index in data at which to start parsing 90 * @return A list of COMPREHENSION-TLV objects parsed 91 * @throws ResultException 92 */ decodeMany(byte[] data, int startIndex)93 public static List<ComprehensionTlv> decodeMany(byte[] data, int startIndex) 94 throws ResultException { 95 ArrayList<ComprehensionTlv> items = new ArrayList<ComprehensionTlv>(); 96 int endIndex = data.length; 97 while (startIndex < endIndex) { 98 ComprehensionTlv ctlv = ComprehensionTlv.decode(data, startIndex); 99 if (ctlv != null) { 100 items.add(ctlv); 101 startIndex = ctlv.mValueIndex + ctlv.mLength; 102 } else { 103 CatLog.d(LOG_TAG, "decodeMany: ctlv is null, stop decoding"); 104 break; 105 } 106 } 107 108 return items; 109 } 110 111 /** 112 * Parses an COMPREHENSION-TLV object from a byte array. 113 * 114 * @param data A byte array containing data to be parsed 115 * @param startIndex Index in data at which to start parsing 116 * @return A COMPREHENSION-TLV object parsed 117 * @throws ResultException 118 */ decode(byte[] data, int startIndex)119 public static ComprehensionTlv decode(byte[] data, int startIndex) 120 throws ResultException { 121 int curIndex = startIndex; 122 int endIndex = data.length; 123 124 try { 125 /* tag */ 126 int tag; 127 boolean cr; // Comprehension required flag 128 int temp = data[curIndex++] & 0xff; 129 switch (temp) { 130 case 0: 131 case 0xff: 132 case 0x80: 133 Rlog.d("CAT ", "decode: unexpected first tag byte=" + Integer.toHexString(temp) + 134 ", startIndex=" + startIndex + " curIndex=" + curIndex + 135 " endIndex=" + endIndex); 136 // Return null which will stop decoding, this has occurred 137 // with Ghana MTN simcard and JDI simcard. 138 return null; 139 140 case 0x7f: // tag is in three-byte format 141 tag = ((data[curIndex] & 0xff) << 8) 142 | (data[curIndex + 1] & 0xff); 143 cr = (tag & 0x8000) != 0; 144 tag &= ~0x8000; 145 curIndex += 2; 146 break; 147 148 default: // tag is in single-byte format 149 tag = temp; 150 cr = (tag & 0x80) != 0; 151 tag &= ~0x80; 152 break; 153 } 154 155 /* length */ 156 int length; 157 temp = data[curIndex++] & 0xff; 158 if (temp < 0x80) { 159 length = temp; 160 } else if (temp == 0x81) { 161 length = data[curIndex++] & 0xff; 162 if (length < 0x80) { 163 throw new ResultException( 164 ResultCode.CMD_DATA_NOT_UNDERSTOOD, 165 "length < 0x80 length=" + Integer.toHexString(length) + 166 " startIndex=" + startIndex + " curIndex=" + curIndex + 167 " endIndex=" + endIndex); 168 } 169 } else if (temp == 0x82) { 170 length = ((data[curIndex] & 0xff) << 8) 171 | (data[curIndex + 1] & 0xff); 172 curIndex += 2; 173 if (length < 0x100) { 174 throw new ResultException( 175 ResultCode.CMD_DATA_NOT_UNDERSTOOD, 176 "two byte length < 0x100 length=" + Integer.toHexString(length) + 177 " startIndex=" + startIndex + " curIndex=" + curIndex + 178 " endIndex=" + endIndex); 179 } 180 } else if (temp == 0x83) { 181 length = ((data[curIndex] & 0xff) << 16) 182 | ((data[curIndex + 1] & 0xff) << 8) 183 | (data[curIndex + 2] & 0xff); 184 curIndex += 3; 185 if (length < 0x10000) { 186 throw new ResultException( 187 ResultCode.CMD_DATA_NOT_UNDERSTOOD, 188 "three byte length < 0x10000 length=0x" + Integer.toHexString(length) + 189 " startIndex=" + startIndex + " curIndex=" + curIndex + 190 " endIndex=" + endIndex); 191 } 192 } else { 193 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD, 194 "Bad length modifer=" + temp + 195 " startIndex=" + startIndex + " curIndex=" + curIndex + 196 " endIndex=" + endIndex); 197 198 } 199 200 return new ComprehensionTlv(tag, cr, length, data, curIndex); 201 202 } catch (IndexOutOfBoundsException e) { 203 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD, 204 "IndexOutOfBoundsException" + " startIndex=" + startIndex + 205 " curIndex=" + curIndex + " endIndex=" + endIndex); 206 } 207 } 208 } 209