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