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 32 public static final int BER_UNKNOWN_TAG = 0x00; 33 public static final int BER_PROACTIVE_COMMAND_TAG = 0xd0; 34 public static final int BER_MENU_SELECTION_TAG = 0xd3; 35 public static final int BER_EVENT_DOWNLOAD_TAG = 0xd6; 36 37 private BerTlv(int tag, List<ComprehensionTlv> ctlvs) { 38 mTag = tag; 39 mCompTlvs = ctlvs; 40 } 41 42 /** 43 * Gets a list of ComprehensionTlv objects contained in this BER-TLV object. 44 * 45 * @return A list of COMPREHENSION-TLV object 46 */ 47 public List<ComprehensionTlv> getComprehensionTlvs() { 48 return mCompTlvs; 49 } 50 51 /** 52 * Gets a tag id of the BER-TLV object. 53 * 54 * @return A tag integer. 55 */ 56 public int getTag() { 57 return mTag; 58 } 59 60 /** 61 * Decodes a BER-TLV object from a byte array. 62 * 63 * @param data A byte array to decode from 64 * @return A BER-TLV object decoded 65 * @throws ResultException 66 */ 67 public static BerTlv decode(byte[] data) throws ResultException { 68 int curIndex = 0; 69 int endIndex = data.length; 70 int tag, length = 0; 71 72 try { 73 /* tag */ 74 tag = data[curIndex++] & 0xff; 75 if (tag == BER_PROACTIVE_COMMAND_TAG) { 76 /* length */ 77 int temp = data[curIndex++] & 0xff; 78 if (temp < 0x80) { 79 length = temp; 80 } else if (temp == 0x81) { 81 temp = data[curIndex++] & 0xff; 82 if (temp < 0x80) { 83 throw new ResultException( 84 ResultCode.CMD_DATA_NOT_UNDERSTOOD, 85 "length < 0x80 length=" + Integer.toHexString(length) + 86 " curIndex=" + curIndex + " endIndex=" + endIndex); 87 88 } 89 length = temp; 90 } else { 91 throw new ResultException( 92 ResultCode.CMD_DATA_NOT_UNDERSTOOD, 93 "Expected first byte to be length or a length tag and < 0x81" + 94 " byte= " + Integer.toHexString(temp) + " curIndex=" + curIndex + 95 " endIndex=" + endIndex); 96 } 97 } else { 98 if (ComprehensionTlvTag.COMMAND_DETAILS.value() == (tag & ~0x80)) { 99 tag = BER_UNKNOWN_TAG; 100 curIndex = 0; 101 } 102 } 103 } catch (IndexOutOfBoundsException e) { 104 throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING, 105 "IndexOutOfBoundsException " + 106 " curIndex=" + curIndex + " endIndex=" + endIndex); 107 } catch (ResultException e) { 108 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD, e.explanation()); 109 } 110 111 /* COMPREHENSION-TLVs */ 112 if (endIndex - curIndex < length) { 113 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD, 114 "Command had extra data endIndex=" + endIndex + " curIndex=" + curIndex + 115 " length=" + length); 116 } 117 118 List<ComprehensionTlv> ctlvs = ComprehensionTlv.decodeMany(data, 119 curIndex); 120 121 return new BerTlv(tag, ctlvs); 122 } 123 } 124