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.gsm;
18 
19 /**
20  * SIM Tag-Length-Value record
21  * TS 102 223 Annex C
22  *
23  * {@hide}
24  *
25  */
26 public class SimTlv
27 {
28     //***** Private Instance Variables
29 
30     byte mRecord[];
31     int mTlvOffset;
32     int mTlvLength;
33     int mCurOffset;
34     int mCurDataOffset;
35     int mCurDataLength;
36     boolean mHasValidTlvObject;
37 
SimTlv(byte[] record, int offset, int length)38     public SimTlv(byte[] record, int offset, int length) {
39         mRecord = record;
40 
41         mTlvOffset = offset;
42         mTlvLength = length;
43         mCurOffset = offset;
44 
45         mHasValidTlvObject = parseCurrentTlvObject();
46     }
47 
nextObject()48     public boolean nextObject() {
49         if (!mHasValidTlvObject) return false;
50         mCurOffset = mCurDataOffset + mCurDataLength;
51         mHasValidTlvObject = parseCurrentTlvObject();
52         return mHasValidTlvObject;
53     }
54 
isValidObject()55     public boolean isValidObject() {
56         return mHasValidTlvObject;
57     }
58 
59     /**
60      * Returns the tag for the current TLV object
61      * Return 0 if !isValidObject()
62      * 0 and 0xff are invalid tag values
63      * valid tags range from 1 - 0xfe
64      */
getTag()65     public int getTag() {
66         if (!mHasValidTlvObject) return 0;
67         return mRecord[mCurOffset] & 0xff;
68     }
69 
70     /**
71      * Returns data associated with current TLV object
72      * returns null if !isValidObject()
73      */
74 
getData()75     public byte[] getData() {
76         if (!mHasValidTlvObject) return null;
77 
78         byte[] ret = new byte[mCurDataLength];
79         System.arraycopy(mRecord, mCurDataOffset, ret, 0, mCurDataLength);
80         return ret;
81     }
82 
83     /**
84      * Updates curDataLength and curDataOffset
85      * @return false on invalid record, true on valid record
86      */
87 
parseCurrentTlvObject()88     private boolean parseCurrentTlvObject() {
89         // 0x00 and 0xff are invalid tag values
90 
91         try {
92             if (mRecord[mCurOffset] == 0 || (mRecord[mCurOffset] & 0xff) == 0xff) {
93                 return false;
94             }
95 
96             if ((mRecord[mCurOffset + 1] & 0xff) < 0x80) {
97                 // one byte length 0 - 0x7f
98                 mCurDataLength = mRecord[mCurOffset + 1] & 0xff;
99                 mCurDataOffset = mCurOffset + 2;
100             } else if ((mRecord[mCurOffset + 1] & 0xff) == 0x81) {
101                 // two byte length 0x80 - 0xff
102                 mCurDataLength = mRecord[mCurOffset + 2] & 0xff;
103                 mCurDataOffset = mCurOffset + 3;
104             } else {
105                 return false;
106             }
107         } catch (ArrayIndexOutOfBoundsException ex) {
108             return false;
109         }
110 
111         if (mCurDataLength + mCurDataOffset > mTlvOffset + mTlvLength) {
112             return false;
113         }
114 
115         return true;
116     }
117 
118 }
119