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