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.stk;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Class for representing COMPREHENSION-TLV objects.
25767a662ecde33c3979bf02b793d392aca0403162Wink Saville *
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see "ETSI TS 101 220 subsection 7.1.1"
27767a662ecde33c3979bf02b793d392aca0403162Wink Saville *
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass ComprehensionTlv {
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mTag;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mCr;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLength;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mValueIndex;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private byte[] mRawValue;
362563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Constructor. Private on purpose. Use
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #decodeMany(byte[], int) decodeMany} or
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #decode(byte[], int) decode} method.
41767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param tag The tag for this object
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cr Comprehension Required flag
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param length Length of the value
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param data Byte array containing the value
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param valueIndex Index in data at which the value starts
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected ComprehensionTlv(int tag, boolean cr, int length, byte[] data,
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int valueIndex) {
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTag = tag;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCr = cr;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLength = length;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mValueIndex = valueIndex;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRawValue = data;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getTag() {
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mTag;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isComprehensionRequired() {
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCr;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getLength() {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mLength;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getValueIndex() {
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mValueIndex;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public byte[] getRawValue() {
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mRawValue;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Parses a list of COMPREHENSION-TLV objects from a byte array.
79767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param data A byte array containing data to be parsed
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param startIndex Index in data at which to start parsing
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A list of COMPREHENSION-TLV objects parsed
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws ResultException
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static List<ComprehensionTlv> decodeMany(byte[] data, int startIndex)
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws ResultException {
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<ComprehensionTlv> items = new ArrayList<ComprehensionTlv>();
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int endIndex = data.length;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (startIndex < endIndex) {
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ComprehensionTlv ctlv = ComprehensionTlv.decode(data, startIndex);
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            items.add(ctlv);
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startIndex = ctlv.mValueIndex + ctlv.mLength;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return items;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Parses an COMPREHENSION-TLV object from a byte array.
100767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param data A byte array containing data to be parsed
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param startIndex Index in data at which to start parsing
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A COMPREHENSION-TLV object parsed
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws ResultException
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static ComprehensionTlv decode(byte[] data, int startIndex)
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws ResultException {
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int curIndex = startIndex;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int endIndex = data.length;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* tag */
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int tag;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean cr; // Comprehension required flag
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int temp = data[curIndex++] & 0xff;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (temp) {
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case 0:
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case 0xff:
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case 0x80:
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case 0x7f: // tag is in three-byte format
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                tag = ((data[curIndex] & 0xff) << 8)
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        | (data[curIndex + 1] & 0xff);
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cr = (tag & 0x8000) != 0;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                tag &= ~0x8000;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curIndex += 2;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default: // tag is in single-byte format
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                tag = temp;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cr = (tag & 0x80) != 0;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                tag &= ~0x80;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* length */
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int length;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            temp = data[curIndex++] & 0xff;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (temp < 0x80) {
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                length = temp;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (temp == 0x81) {
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                length = data[curIndex++] & 0xff;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (length < 0x80) {
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new ResultException(
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            ResultCode.CMD_DATA_NOT_UNDERSTOOD);
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (temp == 0x82) {
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                length = ((data[curIndex] & 0xff) << 8)
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        | (data[curIndex + 1] & 0xff);
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curIndex += 2;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (length < 0x100) {
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new ResultException(
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            ResultCode.CMD_DATA_NOT_UNDERSTOOD);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (temp == 0x83) {
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                length = ((data[curIndex] & 0xff) << 16)
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        | ((data[curIndex + 1] & 0xff) << 8)
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        | (data[curIndex + 2] & 0xff);
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curIndex += 3;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (length < 0x10000) {
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new ResultException(
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            ResultCode.CMD_DATA_NOT_UNDERSTOOD);
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1682563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ComprehensionTlv(tag, cr, length, data, curIndex);
1702563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IndexOutOfBoundsException e) {
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
176