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