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
17package com.android.internal.telephony.gsm;
18
19/**
20 * SIM Tag-Length-Value record
21 * TS 102 223 Annex C
22 *
23 * {@hide}
24 *
25 */
26public 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
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
48    public boolean nextObject() {
49        if (!mHasValidTlvObject) return false;
50        mCurOffset = mCurDataOffset + mCurDataLength;
51        mHasValidTlvObject = parseCurrentTlvObject();
52        return mHasValidTlvObject;
53    }
54
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     */
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
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
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