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.cat.Duration.TimeUnit;
21import com.android.internal.telephony.uicc.IccUtils;
22
23import android.content.res.Resources;
24import android.content.res.Resources.NotFoundException;
25import java.io.UnsupportedEncodingException;
26import java.util.ArrayList;
27import java.util.List;
28
29abstract 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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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