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