10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/*
20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2006 The Android Open Source Project
30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License.
60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at
70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software
110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and
140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License.
150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony.gsm;
180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * SIM Tag-Length-Value record
210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * TS 102 223 Annex C
220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * {@hide}
240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class SimTlv
270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Private Instance Variables
290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    byte mRecord[];
3122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    int mTlvOffset;
3222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    int mTlvLength;
3322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    int mCurOffset;
3422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    int mCurDataOffset;
3522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    int mCurDataLength;
3622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    boolean mHasValidTlvObject;
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public SimTlv(byte[] record, int offset, int length) {
3922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecord = record;
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mTlvOffset = offset;
4222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mTlvLength = length;
4322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mCurOffset = offset;
440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mHasValidTlvObject = parseCurrentTlvObject();
460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean nextObject() {
4922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (!mHasValidTlvObject) return false;
5022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mCurOffset = mCurDataOffset + mCurDataLength;
5122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mHasValidTlvObject = parseCurrentTlvObject();
5222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mHasValidTlvObject;
530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean isValidObject() {
5622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mHasValidTlvObject;
570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Returns the tag for the current TLV object
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Return 0 if !isValidObject()
620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * 0 and 0xff are invalid tag values
630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * valid tags range from 1 - 0xfe
640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public int getTag() {
6622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (!mHasValidTlvObject) return 0;
6722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mRecord[mCurOffset] & 0xff;
680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Returns data associated with current TLV object
720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * returns null if !isValidObject()
730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public byte[] getData() {
7622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (!mHasValidTlvObject) return null;
770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        byte[] ret = new byte[mCurDataLength];
7922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        System.arraycopy(mRecord, mCurDataOffset, ret, 0, mCurDataLength);
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return ret;
810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Updates curDataLength and curDataOffset
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return false on invalid record, true on valid record
860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean parseCurrentTlvObject() {
890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // 0x00 and 0xff are invalid tag values
900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
9222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mRecord[mCurOffset] == 0 || (mRecord[mCurOffset] & 0xff) == 0xff) {
930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return false;
940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if ((mRecord[mCurOffset + 1] & 0xff) < 0x80) {
970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // one byte length 0 - 0x7f
9822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mCurDataLength = mRecord[mCurOffset + 1] & 0xff;
9922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mCurDataOffset = mCurOffset + 2;
10022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if ((mRecord[mCurOffset + 1] & 0xff) == 0x81) {
1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // two byte length 0x80 - 0xff
10222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mCurDataLength = mRecord[mCurOffset + 2] & 0xff;
10322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mCurDataOffset = mCurOffset + 3;
1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return false;
1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (ArrayIndexOutOfBoundsException ex) {
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return false;
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mCurDataLength + mCurDataOffset > mTlvOffset + mTlvLength) {
1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return false;
1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return true;
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
119