19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.internal.telephony.gsm;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * SIM Tag-Length-Value record
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TS 102 223 Annex C
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SimTlv
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //***** Private Instance Variables
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    byte record[];
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int tlvOffset;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int tlvLength;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int curOffset;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int curDataOffset;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int curDataLength;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean hasValidTlvObject;
3704e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville
3804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    public SimTlv(byte[] record, int offset, int length) {
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.record = record;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.tlvOffset = offset;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.tlvLength = length;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        curOffset = offset;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        hasValidTlvObject = parseCurrentTlvObject();
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    public boolean nextObject() {
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!hasValidTlvObject) return false;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        curOffset = curDataOffset + curDataLength;
5104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        hasValidTlvObject = parseCurrentTlvObject();
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return hasValidTlvObject;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5504e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    public boolean isValidObject() {
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return hasValidTlvObject;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the tag for the current TLV object
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return 0 if !isValidObject()
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * 0 and 0xff are invalid tag values
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * valid tags range from 1 - 0xfe
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6504e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    public int getTag() {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!hasValidTlvObject) return 0;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return record[curOffset] & 0xff;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns data associated with current TLV object
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returns null if !isValidObject()
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7404e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville
7504e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    public byte[] getData() {
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!hasValidTlvObject) return null;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        byte[] ret = new byte[curDataLength];
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        System.arraycopy(record, curDataOffset, ret, 0, curDataLength);
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ret;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Updates curDataLength and curDataOffset
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return false on invalid record, true on valid record
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    private boolean parseCurrentTlvObject() {
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // 0x00 and 0xff are invalid tag values
9004e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
9234efc39f256d5833687c7bd7d83258d6394c9307Jaikumar Ganesh            if (record[curOffset] == 0 || (record[curOffset] & 0xff) == 0xff) {
9334efc39f256d5833687c7bd7d83258d6394c9307Jaikumar Ganesh                return false;
9434efc39f256d5833687c7bd7d83258d6394c9307Jaikumar Ganesh            }
9534efc39f256d5833687c7bd7d83258d6394c9307Jaikumar Ganesh
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((record[curOffset + 1] & 0xff) < 0x80) {
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // one byte length 0 - 0x7f
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curDataLength = record[curOffset + 1] & 0xff;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curDataOffset = curOffset + 2;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if ((record[curOffset + 1] & 0xff) == 0x81) {
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // two byte length 0x80 - 0xff
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curDataLength = record[curOffset + 2] & 0xff;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curDataOffset = curOffset + 3;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (ArrayIndexOutOfBoundsException ex) {
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (curDataLength + curDataOffset > tlvOffset + tlvLength) {
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
119