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 record[];
31    int tlvOffset;
32    int tlvLength;
33    int curOffset;
34    int curDataOffset;
35    int curDataLength;
36    boolean hasValidTlvObject;
37
38    public SimTlv(byte[] record, int offset, int length) {
39        this.record = record;
40
41        this.tlvOffset = offset;
42        this.tlvLength = length;
43        curOffset = offset;
44
45        hasValidTlvObject = parseCurrentTlvObject();
46    }
47
48    public boolean nextObject() {
49        if (!hasValidTlvObject) return false;
50        curOffset = curDataOffset + curDataLength;
51        hasValidTlvObject = parseCurrentTlvObject();
52        return hasValidTlvObject;
53    }
54
55    public boolean isValidObject() {
56        return hasValidTlvObject;
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 (!hasValidTlvObject) return 0;
67        return record[curOffset] & 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 (!hasValidTlvObject) return null;
77
78        byte[] ret = new byte[curDataLength];
79        System.arraycopy(record, curDataOffset, ret, 0, curDataLength);
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 (record[curOffset] == 0 || (record[curOffset] & 0xff) == 0xff) {
93                return false;
94            }
95
96            if ((record[curOffset + 1] & 0xff) < 0x80) {
97                // one byte length 0 - 0x7f
98                curDataLength = record[curOffset + 1] & 0xff;
99                curDataOffset = curOffset + 2;
100            } else if ((record[curOffset + 1] & 0xff) == 0x81) {
101                // two byte length 0x80 - 0xff
102                curDataLength = record[curOffset + 2] & 0xff;
103                curDataOffset = curOffset + 3;
104            } else {
105                return false;
106            }
107        } catch (ArrayIndexOutOfBoundsException ex) {
108            return false;
109        }
110
111        if (curDataLength + curDataOffset > tlvOffset + tlvLength) {
112            return false;
113        }
114
115        return true;
116    }
117
118}
119