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 17 package com.android.internal.telephony.cat; 18 19 import java.util.List; 20 21 /** 22 * Class for representing BER-TLV objects. 23 * 24 * @see "ETSI TS 102 223 Annex C" for more information. 25 * 26 * {@hide} 27 */ 28 class BerTlv { 29 private int mTag = BER_UNKNOWN_TAG; 30 private List<ComprehensionTlv> mCompTlvs = null; 31 private boolean mLengthValid = true; 32 33 public static final int BER_UNKNOWN_TAG = 0x00; 34 public static final int BER_PROACTIVE_COMMAND_TAG = 0xd0; 35 public static final int BER_MENU_SELECTION_TAG = 0xd3; 36 public static final int BER_EVENT_DOWNLOAD_TAG = 0xd6; 37 BerTlv(int tag, List<ComprehensionTlv> ctlvs, boolean lengthValid)38 private BerTlv(int tag, List<ComprehensionTlv> ctlvs, boolean lengthValid) { 39 mTag = tag; 40 mCompTlvs = ctlvs; 41 mLengthValid = lengthValid; 42 } 43 44 /** 45 * Gets a list of ComprehensionTlv objects contained in this BER-TLV object. 46 * 47 * @return A list of COMPREHENSION-TLV object 48 */ getComprehensionTlvs()49 public List<ComprehensionTlv> getComprehensionTlvs() { 50 return mCompTlvs; 51 } 52 53 /** 54 * Gets a tag id of the BER-TLV object. 55 * 56 * @return A tag integer. 57 */ getTag()58 public int getTag() { 59 return mTag; 60 } 61 62 /** 63 * Gets if the length of the BER-TLV object is valid 64 * 65 * @return if length valid 66 */ isLengthValid()67 public boolean isLengthValid() { 68 return mLengthValid; 69 } 70 71 /** 72 * Decodes a BER-TLV object from a byte array. 73 * 74 * @param data A byte array to decode from 75 * @return A BER-TLV object decoded 76 * @throws ResultException 77 */ decode(byte[] data)78 public static BerTlv decode(byte[] data) throws ResultException { 79 int curIndex = 0; 80 int endIndex = data.length; 81 int tag, length = 0; 82 boolean isLengthValid = true; 83 84 try { 85 /* tag */ 86 tag = data[curIndex++] & 0xff; 87 if (tag == BER_PROACTIVE_COMMAND_TAG) { 88 /* length */ 89 int temp = data[curIndex++] & 0xff; 90 if (temp < 0x80) { 91 length = temp; 92 } else if (temp == 0x81) { 93 temp = data[curIndex++] & 0xff; 94 if (temp < 0x80) { 95 throw new ResultException( 96 ResultCode.CMD_DATA_NOT_UNDERSTOOD, 97 "length < 0x80 length=" + Integer.toHexString(length) + 98 " curIndex=" + curIndex + " endIndex=" + endIndex); 99 100 } 101 length = temp; 102 } else { 103 throw new ResultException( 104 ResultCode.CMD_DATA_NOT_UNDERSTOOD, 105 "Expected first byte to be length or a length tag and < 0x81" + 106 " byte= " + Integer.toHexString(temp) + " curIndex=" + curIndex + 107 " endIndex=" + endIndex); 108 } 109 } else { 110 if (ComprehensionTlvTag.COMMAND_DETAILS.value() == (tag & ~0x80)) { 111 tag = BER_UNKNOWN_TAG; 112 curIndex = 0; 113 } 114 } 115 } catch (IndexOutOfBoundsException e) { 116 throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING, 117 "IndexOutOfBoundsException " + 118 " curIndex=" + curIndex + " endIndex=" + endIndex); 119 } catch (ResultException e) { 120 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD, e.explanation()); 121 } 122 123 /* COMPREHENSION-TLVs */ 124 if (endIndex - curIndex < length) { 125 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD, 126 "Command had extra data endIndex=" + endIndex + " curIndex=" + curIndex + 127 " length=" + length); 128 } 129 130 List<ComprehensionTlv> ctlvs = ComprehensionTlv.decodeMany(data, 131 curIndex); 132 133 if (tag == BER_PROACTIVE_COMMAND_TAG) { 134 int totalLength = 0; 135 for (ComprehensionTlv item : ctlvs) { 136 int itemLength = item.getLength(); 137 if (itemLength >= 0x80 && itemLength <= 0xFF) { 138 totalLength += itemLength + 3; //3: 'tag'(1 byte) and 'length'(2 bytes). 139 } else if (itemLength >= 0 && itemLength < 0x80) { 140 totalLength += itemLength + 2; //2: 'tag'(1 byte) and 'length'(1 byte). 141 } else { 142 isLengthValid = false; 143 break; 144 } 145 } 146 147 // According to 3gpp11.14, chapter 6.10.6 "Length errors", 148 149 // If the total lengths of the SIMPLE-TLV data objects are not 150 // consistent with the length given in the BER-TLV data object, 151 // then the whole BER-TLV data object shall be rejected. The 152 // result field in the TERMINAL RESPONSE shall have the error 153 // condition "Command data not understood by ME". 154 if (length != totalLength) { 155 isLengthValid = false; 156 } 157 } 158 159 return new BerTlv(tag, ctlvs, isLengthValid); 160 } 161 } 162