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