1/* 2 * Copyright (C) 2006 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 17package com.android.internal.telephony.gsm.stk; 18 19import java.util.ArrayList; 20import 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 */ 30class ComprehensionTlv { 31 private int mTag; 32 private boolean mCr; 33 private int mLength; 34 private int mValueIndex; 35 private byte[] mRawValue; 36 37 /** 38 * Constructor. Private on purpose. Use 39 * {@link #decodeMany(byte[], int) decodeMany} or 40 * {@link #decode(byte[], int) decode} method. 41 * 42 * @param tag The tag for this object 43 * @param cr Comprehension Required flag 44 * @param length Length of the value 45 * @param data Byte array containing the value 46 * @param valueIndex Index in data at which the value starts 47 */ 48 protected ComprehensionTlv(int tag, boolean cr, int length, byte[] data, 49 int valueIndex) { 50 mTag = tag; 51 mCr = cr; 52 mLength = length; 53 mValueIndex = valueIndex; 54 mRawValue = data; 55 } 56 57 public int getTag() { 58 return mTag; 59 } 60 61 public boolean isComprehensionRequired() { 62 return mCr; 63 } 64 65 public int getLength() { 66 return mLength; 67 } 68 69 public int getValueIndex() { 70 return mValueIndex; 71 } 72 73 public byte[] getRawValue() { 74 return mRawValue; 75 } 76 77 /** 78 * Parses a list of COMPREHENSION-TLV objects from a byte array. 79 * 80 * @param data A byte array containing data to be parsed 81 * @param startIndex Index in data at which to start parsing 82 * @return A list of COMPREHENSION-TLV objects parsed 83 * @throws ResultException 84 */ 85 public static List<ComprehensionTlv> decodeMany(byte[] data, int startIndex) 86 throws ResultException { 87 ArrayList<ComprehensionTlv> items = new ArrayList<ComprehensionTlv>(); 88 int endIndex = data.length; 89 while (startIndex < endIndex) { 90 ComprehensionTlv ctlv = ComprehensionTlv.decode(data, startIndex); 91 items.add(ctlv); 92 startIndex = ctlv.mValueIndex + ctlv.mLength; 93 } 94 95 return items; 96 } 97 98 /** 99 * Parses an COMPREHENSION-TLV object from a byte array. 100 * 101 * @param data A byte array containing data to be parsed 102 * @param startIndex Index in data at which to start parsing 103 * @return A COMPREHENSION-TLV object parsed 104 * @throws ResultException 105 */ 106 public static ComprehensionTlv decode(byte[] data, int startIndex) 107 throws ResultException { 108 try { 109 int curIndex = startIndex; 110 int endIndex = data.length; 111 112 /* tag */ 113 int tag; 114 boolean cr; // Comprehension required flag 115 int temp = data[curIndex++] & 0xff; 116 switch (temp) { 117 case 0: 118 case 0xff: 119 case 0x80: 120 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 121 122 case 0x7f: // tag is in three-byte format 123 tag = ((data[curIndex] & 0xff) << 8) 124 | (data[curIndex + 1] & 0xff); 125 cr = (tag & 0x8000) != 0; 126 tag &= ~0x8000; 127 curIndex += 2; 128 break; 129 130 default: // tag is in single-byte format 131 tag = temp; 132 cr = (tag & 0x80) != 0; 133 tag &= ~0x80; 134 break; 135 } 136 137 /* length */ 138 int length; 139 temp = data[curIndex++] & 0xff; 140 if (temp < 0x80) { 141 length = temp; 142 } else if (temp == 0x81) { 143 length = data[curIndex++] & 0xff; 144 if (length < 0x80) { 145 throw new ResultException( 146 ResultCode.CMD_DATA_NOT_UNDERSTOOD); 147 } 148 } else if (temp == 0x82) { 149 length = ((data[curIndex] & 0xff) << 8) 150 | (data[curIndex + 1] & 0xff); 151 curIndex += 2; 152 if (length < 0x100) { 153 throw new ResultException( 154 ResultCode.CMD_DATA_NOT_UNDERSTOOD); 155 } 156 } else if (temp == 0x83) { 157 length = ((data[curIndex] & 0xff) << 16) 158 | ((data[curIndex + 1] & 0xff) << 8) 159 | (data[curIndex + 2] & 0xff); 160 curIndex += 3; 161 if (length < 0x10000) { 162 throw new ResultException( 163 ResultCode.CMD_DATA_NOT_UNDERSTOOD); 164 } 165 } else { 166 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 167 } 168 169 return new ComprehensionTlv(tag, cr, length, data, curIndex); 170 171 } catch (IndexOutOfBoundsException e) { 172 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 173 } 174 } 175} 176