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 
17 package com.android.internal.telephony.gsm;
18 
19 import android.compat.annotation.UnsupportedAppUsage;
20 import android.os.Build;
21 
22 /**
23  * SIM Tag-Length-Value record
24  * TS 102 223 Annex C
25  *
26  * {@hide}
27  *
28  */
29 public class SimTlv
30 {
31     //***** Private Instance Variables
32 
33     byte mRecord[];
34     int mTlvOffset;
35     int mTlvLength;
36     int mCurOffset;
37     int mCurDataOffset;
38     int mCurDataLength;
39     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
40     boolean mHasValidTlvObject;
41 
42     @UnsupportedAppUsage
SimTlv(byte[] record, int offset, int length)43     public SimTlv(byte[] record, int offset, int length) {
44         mRecord = record;
45 
46         mTlvOffset = offset;
47         mTlvLength = length;
48         mCurOffset = offset;
49 
50         mHasValidTlvObject = parseCurrentTlvObject();
51     }
52 
53     @UnsupportedAppUsage
nextObject()54     public boolean nextObject() {
55         if (!mHasValidTlvObject) return false;
56         mCurOffset = mCurDataOffset + mCurDataLength;
57         mHasValidTlvObject = parseCurrentTlvObject();
58         return mHasValidTlvObject;
59     }
60 
61     @UnsupportedAppUsage
isValidObject()62     public boolean isValidObject() {
63         return mHasValidTlvObject;
64     }
65 
66     /**
67      * Returns the tag for the current TLV object
68      * Return 0 if !isValidObject()
69      * 0 and 0xff are invalid tag values
70      * valid tags range from 1 - 0xfe
71      */
72     @UnsupportedAppUsage
getTag()73     public int getTag() {
74         if (!mHasValidTlvObject) return 0;
75         return mRecord[mCurOffset] & 0xff;
76     }
77 
78     /**
79      * Returns data associated with current TLV object
80      * returns null if !isValidObject()
81      */
82 
83     @UnsupportedAppUsage
getData()84     public byte[] getData() {
85         if (!mHasValidTlvObject) return null;
86 
87         byte[] ret = new byte[mCurDataLength];
88         System.arraycopy(mRecord, mCurDataOffset, ret, 0, mCurDataLength);
89         return ret;
90     }
91 
92     /**
93      * Updates curDataLength and curDataOffset
94      * @return false on invalid record, true on valid record
95      */
96 
parseCurrentTlvObject()97     private boolean parseCurrentTlvObject() {
98         // 0x00 and 0xff are invalid tag values
99 
100         try {
101             if (mRecord[mCurOffset] == 0 || (mRecord[mCurOffset] & 0xff) == 0xff) {
102                 return false;
103             }
104 
105             if ((mRecord[mCurOffset + 1] & 0xff) < 0x80) {
106                 // one byte length 0 - 0x7f
107                 mCurDataLength = mRecord[mCurOffset + 1] & 0xff;
108                 mCurDataOffset = mCurOffset + 2;
109             } else if ((mRecord[mCurOffset + 1] & 0xff) == 0x81) {
110                 // two byte length 0x80 - 0xff
111                 mCurDataLength = mRecord[mCurOffset + 2] & 0xff;
112                 mCurDataOffset = mCurOffset + 3;
113             } else {
114                 return false;
115             }
116         } catch (ArrayIndexOutOfBoundsException ex) {
117             return false;
118         }
119 
120         if (mCurDataLength + mCurDataOffset > mTlvOffset + mTlvLength) {
121             return false;
122         }
123 
124         return true;
125     }
126 
127 }
128