1 /* 2 * Copyright (C) 2006-2007 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package com.android.internal.telephony.cat; 18 19 import android.compat.annotation.UnsupportedAppUsage; 20 import android.os.Build; 21 22 import com.android.internal.telephony.GsmAlphabet; 23 import com.android.internal.telephony.cat.Duration.TimeUnit; 24 import com.android.internal.telephony.uicc.IccUtils; 25 26 import java.io.UnsupportedEncodingException; 27 import java.util.ArrayList; 28 import java.util.List; 29 30 abstract class ValueParser { 31 32 /** 33 * Search for a Command Details object from a list. 34 * 35 * @param ctlv List of ComprehensionTlv objects used for search 36 * @return An CtlvCommandDetails object found from the objects. If no 37 * Command Details object is found, ResultException is thrown. 38 * @throws ResultException 39 */ retrieveCommandDetails(ComprehensionTlv ctlv)40 static CommandDetails retrieveCommandDetails(ComprehensionTlv ctlv) 41 throws ResultException { 42 43 CommandDetails cmdDet = new CommandDetails(); 44 byte[] rawValue = ctlv.getRawValue(); 45 int valueIndex = ctlv.getValueIndex(); 46 try { 47 cmdDet.compRequired = ctlv.isComprehensionRequired(); 48 cmdDet.commandNumber = rawValue[valueIndex] & 0xff; 49 cmdDet.typeOfCommand = rawValue[valueIndex + 1] & 0xff; 50 cmdDet.commandQualifier = rawValue[valueIndex + 2] & 0xff; 51 return cmdDet; 52 } catch (IndexOutOfBoundsException e) { 53 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 54 } 55 } 56 57 /** 58 * Search for a Device Identities object from a list. 59 * 60 * @param ctlv List of ComprehensionTlv objects used for search 61 * @return An CtlvDeviceIdentities object found from the objects. If no 62 * Command Details object is found, ResultException is thrown. 63 * @throws ResultException 64 */ 65 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) retrieveDeviceIdentities(ComprehensionTlv ctlv)66 static DeviceIdentities retrieveDeviceIdentities(ComprehensionTlv ctlv) 67 throws ResultException { 68 69 DeviceIdentities devIds = new DeviceIdentities(); 70 byte[] rawValue = ctlv.getRawValue(); 71 int valueIndex = ctlv.getValueIndex(); 72 try { 73 devIds.sourceId = rawValue[valueIndex] & 0xff; 74 devIds.destinationId = rawValue[valueIndex + 1] & 0xff; 75 return devIds; 76 } catch (IndexOutOfBoundsException e) { 77 throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING); 78 } 79 } 80 81 /** 82 * Retrieves Duration information from the Duration COMPREHENSION-TLV 83 * object. 84 * 85 * @param ctlv A Text Attribute COMPREHENSION-TLV object 86 * @return A Duration object 87 * @throws ResultException 88 */ retrieveDuration(ComprehensionTlv ctlv)89 static Duration retrieveDuration(ComprehensionTlv ctlv) throws ResultException { 90 int timeInterval = 0; 91 TimeUnit timeUnit = TimeUnit.SECOND; 92 93 byte[] rawValue = ctlv.getRawValue(); 94 int valueIndex = ctlv.getValueIndex(); 95 96 try { 97 timeUnit = TimeUnit.values()[(rawValue[valueIndex] & 0xff)]; 98 timeInterval = rawValue[valueIndex + 1] & 0xff; 99 } catch (IndexOutOfBoundsException e) { 100 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 101 } 102 return new Duration(timeInterval, timeUnit); 103 } 104 105 /** 106 * Retrieves Item information from the COMPREHENSION-TLV object. 107 * 108 * @param ctlv A Text Attribute COMPREHENSION-TLV object 109 * @return An Item 110 * @throws ResultException 111 */ retrieveItem(ComprehensionTlv ctlv)112 static Item retrieveItem(ComprehensionTlv ctlv) throws ResultException { 113 Item item = null; 114 115 byte[] rawValue = ctlv.getRawValue(); 116 int valueIndex = ctlv.getValueIndex(); 117 int length = ctlv.getLength(); 118 119 if (length != 0) { 120 int textLen = length - 1; 121 122 try { 123 int id = rawValue[valueIndex] & 0xff; 124 String text = IccUtils.adnStringFieldToString(rawValue, 125 valueIndex + 1, textLen); 126 item = new Item(id, text); 127 } catch (IndexOutOfBoundsException e) { 128 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 129 } 130 } 131 132 return item; 133 } 134 135 /** 136 * Retrieves Item id information from the COMPREHENSION-TLV object. 137 * 138 * @param ctlv A Text Attribute COMPREHENSION-TLV object 139 * @return An Item id 140 * @throws ResultException 141 */ retrieveItemId(ComprehensionTlv ctlv)142 static int retrieveItemId(ComprehensionTlv ctlv) throws ResultException { 143 int id = 0; 144 145 byte[] rawValue = ctlv.getRawValue(); 146 int valueIndex = ctlv.getValueIndex(); 147 148 try { 149 id = rawValue[valueIndex] & 0xff; 150 } catch (IndexOutOfBoundsException e) { 151 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 152 } 153 154 return id; 155 } 156 157 /** 158 * Retrieves icon id from an Icon Identifier COMPREHENSION-TLV object 159 * 160 * @param ctlv An Icon Identifier COMPREHENSION-TLV object 161 * @return IconId instance 162 * @throws ResultException 163 */ retrieveIconId(ComprehensionTlv ctlv)164 static IconId retrieveIconId(ComprehensionTlv ctlv) throws ResultException { 165 IconId id = new IconId(); 166 167 byte[] rawValue = ctlv.getRawValue(); 168 int valueIndex = ctlv.getValueIndex(); 169 try { 170 id.selfExplanatory = (rawValue[valueIndex++] & 0xff) == 0x00; 171 id.recordNumber = rawValue[valueIndex] & 0xff; 172 } catch (IndexOutOfBoundsException e) { 173 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 174 } 175 176 return id; 177 } 178 179 /** 180 * Retrieves item icons id from an Icon Identifier List COMPREHENSION-TLV 181 * object 182 * 183 * @param ctlv An Item Icon List Identifier COMPREHENSION-TLV object 184 * @return ItemsIconId instance 185 * @throws ResultException 186 */ retrieveItemsIconId(ComprehensionTlv ctlv)187 static ItemsIconId retrieveItemsIconId(ComprehensionTlv ctlv) 188 throws ResultException { 189 CatLog.d("ValueParser", "retrieveItemsIconId:"); 190 ItemsIconId id = new ItemsIconId(); 191 192 byte[] rawValue = ctlv.getRawValue(); 193 int valueIndex = ctlv.getValueIndex(); 194 int numOfItems = ctlv.getLength() - 1; 195 id.recordNumbers = new int[numOfItems]; 196 197 try { 198 // get icon self-explanatory 199 id.selfExplanatory = (rawValue[valueIndex++] & 0xff) == 0x00; 200 201 for (int index = 0; index < numOfItems;) { 202 id.recordNumbers[index++] = rawValue[valueIndex++]; 203 } 204 } catch (IndexOutOfBoundsException e) { 205 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 206 } 207 return id; 208 } 209 210 /** 211 * Retrieves text attribute information from the Text Attribute 212 * COMPREHENSION-TLV object. 213 * 214 * @param ctlv A Text Attribute COMPREHENSION-TLV object 215 * @return A list of TextAttribute objects 216 * @throws ResultException 217 */ 218 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) retrieveTextAttribute(ComprehensionTlv ctlv)219 static List<TextAttribute> retrieveTextAttribute(ComprehensionTlv ctlv) 220 throws ResultException { 221 ArrayList<TextAttribute> lst = new ArrayList<TextAttribute>(); 222 223 byte[] rawValue = ctlv.getRawValue(); 224 int valueIndex = ctlv.getValueIndex(); 225 int length = ctlv.getLength(); 226 227 if (length != 0) { 228 // Each attribute is consisted of four bytes 229 int itemCount = length / 4; 230 231 try { 232 for (int i = 0; i < itemCount; i++, valueIndex += 4) { 233 int start = rawValue[valueIndex] & 0xff; 234 int textLength = rawValue[valueIndex + 1] & 0xff; 235 int format = rawValue[valueIndex + 2] & 0xff; 236 int colorValue = rawValue[valueIndex + 3] & 0xff; 237 238 int alignValue = format & 0x03; 239 TextAlignment align = TextAlignment.fromInt(alignValue); 240 241 int sizeValue = (format >> 2) & 0x03; 242 FontSize size = FontSize.fromInt(sizeValue); 243 if (size == null) { 244 // Font size value is not defined. Use default. 245 size = FontSize.NORMAL; 246 } 247 248 boolean bold = (format & 0x10) != 0; 249 boolean italic = (format & 0x20) != 0; 250 boolean underlined = (format & 0x40) != 0; 251 boolean strikeThrough = (format & 0x80) != 0; 252 253 TextColor color = TextColor.fromInt(colorValue); 254 255 TextAttribute attr = new TextAttribute(start, textLength, 256 align, size, bold, italic, underlined, 257 strikeThrough, color); 258 lst.add(attr); 259 } 260 261 return lst; 262 263 } catch (IndexOutOfBoundsException e) { 264 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 265 } 266 } 267 return null; 268 } 269 270 271 /** 272 * Retrieves alpha identifier from an Alpha Identifier COMPREHENSION-TLV 273 * object. 274 * 275 * @param ctlv An Alpha Identifier COMPREHENSION-TLV object 276 * @return String corresponding to the alpha identifier 277 * @throws ResultException 278 */ 279 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) retrieveAlphaId(ComprehensionTlv ctlv, boolean noAlphaUsrCnf)280 static String retrieveAlphaId(ComprehensionTlv ctlv, boolean noAlphaUsrCnf) 281 throws ResultException { 282 283 if (ctlv != null) { 284 byte[] rawValue = ctlv.getRawValue(); 285 int valueIndex = ctlv.getValueIndex(); 286 int length = ctlv.getLength(); 287 if (length != 0) { 288 try { 289 return IccUtils.adnStringFieldToString(rawValue, valueIndex, 290 length); 291 } catch (IndexOutOfBoundsException e) { 292 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 293 } 294 } else { 295 CatLog.d("ValueParser", "Alpha Id length=" + length); 296 return null; 297 } 298 } else { 299 /* Per 3GPP specification 102.223, 300 * if the alpha identifier is not provided by the UICC, 301 * the terminal MAY give information to the user 302 * noAlphaUsrCnf defines if you need to show user confirmation or not 303 */ 304 return (noAlphaUsrCnf ? null : CatService.STK_DEFAULT); 305 } 306 } 307 308 /** 309 * Retrieves text from the Text COMPREHENSION-TLV object, and decodes it 310 * into a Java String. 311 * 312 * @param ctlv A Text COMPREHENSION-TLV object 313 * @return A Java String object decoded from the Text object 314 * @throws ResultException 315 */ 316 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) retrieveTextString(ComprehensionTlv ctlv)317 static String retrieveTextString(ComprehensionTlv ctlv) throws ResultException { 318 byte[] rawValue = ctlv.getRawValue(); 319 int valueIndex = ctlv.getValueIndex(); 320 byte codingScheme = 0x00; 321 String text = null; 322 int textLen = ctlv.getLength(); 323 324 // In case the text length is 0, return a null string. 325 if (textLen == 0) { 326 return text; 327 } else { 328 // one byte is coding scheme 329 textLen -= 1; 330 } 331 332 try { 333 codingScheme = (byte) (rawValue[valueIndex] & 0x0c); 334 335 if (codingScheme == 0x00) { // GSM 7-bit packed 336 text = GsmAlphabet.gsm7BitPackedToString(rawValue, 337 valueIndex + 1, (textLen * 8) / 7); 338 } else if (codingScheme == 0x04) { // GSM 8-bit unpacked 339 text = GsmAlphabet.gsm8BitUnpackedToString(rawValue, 340 valueIndex + 1, textLen); 341 } else if (codingScheme == 0x08) { // UCS2 342 text = new String(rawValue, valueIndex + 1, textLen, "UTF-16"); 343 } else { 344 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 345 } 346 347 return text; 348 } catch (IndexOutOfBoundsException e) { 349 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 350 } catch (UnsupportedEncodingException e) { 351 // This should never happen. 352 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 353 } 354 } 355 } 356