content: /*
   * Copyright (C) 2006-2007 Google Inc.
   *
   * Licensed under the Apache License, Version 2.0 (the "License"); you may not
   * use this file except in compliance with the License. You may obtain a copy of
   * the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   * License for the specific language governing permissions and limitations under
   * the License.
   */
  
  package com.android.internal.telephony.cat;
  
  import com.android.internal.telephony.GsmAlphabet;
  import com.android.internal.telephony.cat.Duration.TimeUnit;
  import com.android.internal.telephony.uicc.IccUtils;
  
  import android.annotation.UnsupportedAppUsage;
  import android.content.res.Resources;
  import android.content.res.Resources.NotFoundException;
  import java.io.UnsupportedEncodingException;
  import java.util.ArrayList;
  import java.util.List;
  
  abstract class ValueParser {
  
      /**
       * Search for a Command Details object from a list.
       *
       * @param ctlv List of ComprehensionTlv objects used for search
       * @return An CtlvCommandDetails object found from the objects. If no
       *         Command Details object is found, ResultException is thrown.
       * @throws ResultException
       */
      static CommandDetails retrieveCommandDetails(ComprehensionTlv ctlv)
              throws ResultException {
  
          CommandDetails cmdDet = new CommandDetails();
          byte[] rawValue = ctlv.getRawValue();
          int valueIndex = ctlv.getValueIndex();
          try {
              cmdDet.compRequired = ctlv.isComprehensionRequired();
              cmdDet.commandNumber = rawValue[valueIndex] & 0xff;
              cmdDet.typeOfCommand = rawValue[valueIndex + 1] & 0xff;
              cmdDet.commandQualifier = rawValue[valueIndex + 2] & 0xff;
              return cmdDet;
          } catch (IndexOutOfBoundsException e) {
              throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
          }
      }
  
      /**
       * Search for a Device Identities object from a list.
       *
       * @param ctlv List of ComprehensionTlv objects used for search
       * @return An CtlvDeviceIdentities object found from the objects. If no
       *         Command Details object is found, ResultException is thrown.
       * @throws ResultException
       */
      static DeviceIdentities retrieveDeviceIdentities(ComprehensionTlv ctlv)
              throws ResultException {
  
          DeviceIdentities devIds = new DeviceIdentities();
          byte[] rawValue = ctlv.getRawValue();
          int valueIndex = ctlv.getValueIndex();
          try {
              devIds.sourceId = rawValue[valueIndex] & 0xff;
              devIds.destinationId = rawValue[valueIndex + 1] & 0xff;
              return devIds;
          } catch (IndexOutOfBoundsException e) {
              throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
          }
      }
  
      /**
       * Retrieves Duration information from the Duration COMPREHENSION-TLV
       * object.
       *
       * @param ctlv A Text Attribute COMPREHENSION-TLV object
       * @return A Duration object
       * @throws ResultException
       */
      static Duration retrieveDuration(ComprehensionTlv ctlv) throws ResultException {
          int timeInterval = 0;
          TimeUnit timeUnit = TimeUnit.SECOND;
  
          byte[] rawValue = ctlv.getRawValue();
          int valueIndex = ctlv.getValueIndex();
  
          try {
              timeUnit = TimeUnit.values()[(rawValue[valueIndex] & 0xff)];
              timeInterval = rawValue[valueIndex + 1] & 0xff;
          } catch (IndexOutOfBoundsException e) {
              throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
          }
          return new Duration(timeInterval, timeUnit);
      }
  
      /**
       * Retrieves Item information from the COMPREHENSION-TLV object.
       *
       * @param ctlv A Text Attribute COMPREHENSION-TLV object
       * @return An Item
       * @throws ResultException
       */
      static Item retrieveItem(ComprehensionTlv ctlv) throws ResultException {
          Item item = null;
  
          byte[] rawValue = ctlv.getRawValue();
          int valueIndex = ctlv.getValueIndex();
          int length = ctlv.getLength();
  
          if (length != 0) {
              int textLen = length - 1;
  
              try {
                  int id = rawValue[valueIndex] & 0xff;
                  String text = IccUtils.adnStringFieldToString(rawValue,
                          valueIndex + 1, textLen);
                  item = new Item(id, text);
              } catch (IndexOutOfBoundsException e) {
                  throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
              }
          }
  
          return item;
      }
  
      /**
       * Retrieves Item id information from the COMPREHENSION-TLV object.
       *
       * @param ctlv A Text Attribute COMPREHENSION-TLV object
       * @return An Item id
       * @throws ResultException
       */
      static int retrieveItemId(ComprehensionTlv ctlv) throws ResultException {
          int id = 0;
  
          byte[] rawValue = ctlv.getRawValue();
          int valueIndex = ctlv.getValueIndex();
  
          try {
              id = rawValue[valueIndex] & 0xff;
          } catch (IndexOutOfBoundsException e) {
              throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
          }
  
          return id;
      }
  
      /**
       * Retrieves icon id from an Icon Identifier COMPREHENSION-TLV object
       *
       * @param ctlv An Icon Identifier COMPREHENSION-TLV object
       * @return IconId instance
       * @throws ResultException
       */
      static IconId retrieveIconId(ComprehensionTlv ctlv) throws ResultException {
          IconId id = new IconId();
  
          byte[] rawValue = ctlv.getRawValue();
          int valueIndex = ctlv.getValueIndex();
          try {
              id.selfExplanatory = (rawValue[valueIndex++] & 0xff) == 0x00;
              id.recordNumber = rawValue[valueIndex] & 0xff;
          } catch (IndexOutOfBoundsException e) {
              throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
          }
  
          return id;
      }
  
      /**
       * Retrieves item icons id from an Icon Identifier List COMPREHENSION-TLV
       * object
       *
       * @param ctlv An Item Icon List Identifier COMPREHENSION-TLV object
       * @return ItemsIconId instance
       * @throws ResultException
       */
      static ItemsIconId retrieveItemsIconId(ComprehensionTlv ctlv)
              throws ResultException {
          CatLog.d("ValueParser", "retrieveItemsIconId:");
          ItemsIconId id = new ItemsIconId();
  
          byte[] rawValue = ctlv.getRawValue();
          int valueIndex = ctlv.getValueIndex();
          int numOfItems = ctlv.getLength() - 1;
          id.recordNumbers = new int[numOfItems];
  
          try {
              // get icon self-explanatory
              id.selfExplanatory = (rawValue[valueIndex++] & 0xff) == 0x00;
  
              for (int index = 0; index < numOfItems;) {
                  id.recordNumbers[index++] = rawValue[valueIndex++];
              }
          } catch (IndexOutOfBoundsException e) {
              throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
          }
          return id;
      }
  
      /**
       * Retrieves text attribute information from the Text Attribute
       * COMPREHENSION-TLV object.
       *
       * @param ctlv A Text Attribute COMPREHENSION-TLV object
       * @return A list of TextAttribute objects
       * @throws ResultException
       */
      @UnsupportedAppUsage
      static List<TextAttribute> retrieveTextAttribute(ComprehensionTlv ctlv)
              throws ResultException {
          ArrayList<TextAttribute> lst = new ArrayList<TextAttribute>();
  
          byte[] rawValue = ctlv.getRawValue();
          int valueIndex = ctlv.getValueIndex();
          int length = ctlv.getLength();
  
          if (length != 0) {
              // Each attribute is consisted of four bytes
              int itemCount = length / 4;
  
              try {
                  for (int i = 0; i < itemCount; i++, valueIndex += 4) {
                      int start = rawValue[valueIndex] & 0xff;
                      int textLength = rawValue[valueIndex + 1] & 0xff;
                      int format = rawValue[valueIndex + 2] & 0xff;
                      int colorValue = rawValue[valueIndex + 3] & 0xff;
  
                      int alignValue = format & 0x03;
                      TextAlignment align = TextAlignment.fromInt(alignValue);
  
                      int sizeValue = (format >> 2) & 0x03;
                      FontSize size = FontSize.fromInt(sizeValue);
                      if (size == null) {
                          // Font size value is not defined. Use default.
                          size = FontSize.NORMAL;
                      }
  
                      boolean bold = (format & 0x10) != 0;
                      boolean italic = (format & 0x20) != 0;
                      boolean underlined = (format & 0x40) != 0;
                      boolean strikeThrough = (format & 0x80) != 0;
  
                      TextColor color = TextColor.fromInt(colorValue);
  
                      TextAttribute attr = new TextAttribute(start, textLength,
                              align, size, bold, italic, underlined,
                              strikeThrough, color);
                      lst.add(attr);
                  }
  
                  return lst;
  
              } catch (IndexOutOfBoundsException e) {
                  throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
              }
          }
          return null;
      }
  
  
      /**
       * Retrieves alpha identifier from an Alpha Identifier COMPREHENSION-TLV
       * object.
       *
       * @param ctlv An Alpha Identifier COMPREHENSION-TLV object
       * @return String corresponding to the alpha identifier
       * @throws ResultException
       */
      @UnsupportedAppUsage
      static String retrieveAlphaId(ComprehensionTlv ctlv) throws ResultException {
  
          if (ctlv != null) {
              byte[] rawValue = ctlv.getRawValue();
              int valueIndex = ctlv.getValueIndex();
              int length = ctlv.getLength();
              if (length != 0) {
                  try {
                      return IccUtils.adnStringFieldToString(rawValue, valueIndex,
                              length);
                  } catch (IndexOutOfBoundsException e) {
                      throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
                  }
              } else {
                  CatLog.d("ValueParser", "Alpha Id length=" + length);
                  return null;
              }
          } else {
              /* Per 3GPP specification 102.223,
               * if the alpha identifier is not provided by the UICC,
               * the terminal MAY give information to the user
               * noAlphaUsrCnf defines if you need to show user confirmation or not
               */
              boolean noAlphaUsrCnf = false;
              Resources resource = Resources.getSystem();
              try {
                  noAlphaUsrCnf = resource.getBoolean(
                          com.android.internal.R.bool.config_stkNoAlphaUsrCnf);
              } catch (NotFoundException e) {
                  noAlphaUsrCnf = false;
              }
              return (noAlphaUsrCnf ? null : CatService.STK_DEFAULT);
          }
      }
  
      /**
       * Retrieves text from the Text COMPREHENSION-TLV object, and decodes it
       * into a Java String.
       *
       * @param ctlv A Text COMPREHENSION-TLV object
       * @return A Java String object decoded from the Text object
       * @throws ResultException
       */
      @UnsupportedAppUsage
      static String retrieveTextString(ComprehensionTlv ctlv) throws ResultException {
          byte[] rawValue = ctlv.getRawValue();
          int valueIndex = ctlv.getValueIndex();
          byte codingScheme = 0x00;
          String text = null;
          int textLen = ctlv.getLength();
  
          // In case the text length is 0, return a null string.
          if (textLen == 0) {
              return text;
          } else {
              // one byte is coding scheme
              textLen -= 1;
          }
  
          try {
              codingScheme = (byte) (rawValue[valueIndex] & 0x0c);
  
              if (codingScheme == 0x00) { // GSM 7-bit packed
                  text = GsmAlphabet.gsm7BitPackedToString(rawValue,
                          valueIndex + 1, (textLen * 8) / 7);
              } else if (codingScheme == 0x04) { // GSM 8-bit unpacked
                  text = GsmAlphabet.gsm8BitUnpackedToString(rawValue,
                          valueIndex + 1, textLen);
              } else if (codingScheme == 0x08) { // UCS2
                  text = new String(rawValue, valueIndex + 1, textLen, "UTF-16");
              } else {
                  throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
              }
  
              return text;
          } catch (IndexOutOfBoundsException e) {
              throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
          } catch (UnsupportedEncodingException e) {
              // This should never happen.
              throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
          }
      }
  }
  