content: /*
   * Copyright (C) 2009 The Android Open Source Project
   *
   * 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.cdma;
  
  import android.annotation.UnsupportedAppUsage;
  import android.content.Context;
  import android.content.res.Resources;
  import android.content.res.XmlResourceParser;
  import android.os.PersistableBundle;
  import android.telephony.CarrierConfigManager;
  import android.telephony.Rlog;
  import android.util.Xml;
  
  import com.android.internal.telephony.Phone;
  import com.android.internal.util.XmlUtils;
  
  
  import org.xmlpull.v1.XmlPullParser;
  import org.xmlpull.v1.XmlPullParserException;
  
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.IOException;
  import java.util.HashMap;
  
  /**
   * EriManager loads the ERI file definitions and manages the CDMA roaming information.
   *
   */
  public class EriManager {
  
      class EriFile {
  
          int mVersionNumber;                      // File version number
          int mNumberOfEriEntries;                 // Number of entries
          int mEriFileType;                        // Eri Phase 0/1
          //int mNumberOfIconImages;               // reserved for future use
          //int mIconImageType;                    // reserved for future use
          String[] mCallPromptId;                  // reserved for future use
          HashMap<Integer, EriInfo> mRoamIndTable; // Roaming Indicator Table
  
          EriFile() {
              mVersionNumber = -1;
              mNumberOfEriEntries = 0;
              mEriFileType = -1;
              mCallPromptId = new String[] { "", "", "" };
              mRoamIndTable = new HashMap<Integer, EriInfo>();
          }
      }
  
      class EriDisplayInformation {
          int mEriIconIndex;
          int mEriIconMode;
          @UnsupportedAppUsage
          String mEriIconText;
  
          EriDisplayInformation(int eriIconIndex, int eriIconMode, String eriIconText) {
              mEriIconIndex = eriIconIndex;
              mEriIconMode = eriIconMode;
              mEriIconText = eriIconText;
          }
  
  //        public void setParameters(int eriIconIndex, int eriIconMode, String eriIconText){
  //            mEriIconIndex = eriIconIndex;
  //            mEriIconMode = eriIconMode;
  //            mEriIconText = eriIconText;
  //        }
  
          @Override
          public String toString() {
              return "EriDisplayInformation: {" + " IconIndex: " + mEriIconIndex + " EriIconMode: "
                      + mEriIconMode + " EriIconText: " + mEriIconText + " }";
          }
      }
  
      private static final String LOG_TAG = "EriManager";
      private static final boolean DBG = true;
      private static final boolean VDBG = false;
  
      public static final int ERI_FROM_XML   = 0;
      static final int ERI_FROM_FILE_SYSTEM  = 1;
      static final int ERI_FROM_MODEM        = 2;
  
      private Context mContext;
      private int mEriFileSource = ERI_FROM_XML;
      private boolean mIsEriFileLoaded;
      private EriFile mEriFile;
      private final Phone mPhone;
  
      public EriManager(Phone phone, int eriFileSource) {
          mPhone = phone;
          mContext = mPhone.getContext();
          mEriFileSource = eriFileSource;
          mEriFile = new EriFile();
      }
  
      public void dispose() {
          mEriFile = new EriFile();
          mIsEriFileLoaded = false;
      }
  
  
      public void loadEriFile() {
          switch (mEriFileSource) {
          case ERI_FROM_MODEM:
              loadEriFileFromModem();
              break;
  
          case ERI_FROM_FILE_SYSTEM:
              loadEriFileFromFileSystem();
              break;
  
          case ERI_FROM_XML:
          default:
              loadEriFileFromXml();
              break;
          }
      }
  
      /**
       * Load the ERI file from the MODEM through chipset specific RIL_REQUEST_OEM_HOOK
       *
       * In this case the ERI file can be updated from the Phone Support Tool available
       * from the Chipset vendor
       */
      private void loadEriFileFromModem() {
          // NOT IMPLEMENTED, Chipset vendor/Operator specific
      }
  
      /**
       * Load the ERI file from a File System file
       *
       * In this case the a Phone Support Tool to update the ERI file must be provided
       * to the Operator
       */
      private void loadEriFileFromFileSystem() {
          // NOT IMPLEMENTED, Chipset vendor/Operator specific
      }
  
      /**
       * Load the ERI file from the application framework resources encoded in XML
       *
       */
      private void loadEriFileFromXml() {
          XmlPullParser parser = null;
          FileInputStream stream = null;
          Resources r = mContext.getResources();
  
          try {
              if (DBG) Rlog.d(LOG_TAG, "loadEriFileFromXml: check for alternate file");
              stream = new FileInputStream(
                              r.getString(com.android.internal.R.string.alternate_eri_file));
              parser = Xml.newPullParser();
              parser.setInput(stream, null);
              if (DBG) Rlog.d(LOG_TAG, "loadEriFileFromXml: opened alternate file");
          } catch (FileNotFoundException e) {
              if (DBG) Rlog.d(LOG_TAG, "loadEriFileFromXml: no alternate file");
              parser = null;
          } catch (XmlPullParserException e) {
              if (DBG) Rlog.d(LOG_TAG, "loadEriFileFromXml: no parser for alternate file");
              parser = null;
          }
  
          if (parser == null) {
              String eriFile = null;
  
              CarrierConfigManager configManager = (CarrierConfigManager)
                      mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
              if (configManager != null) {
                  PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId());
                  if (b != null) {
                      eriFile = b.getString(CarrierConfigManager.KEY_CARRIER_ERI_FILE_NAME_STRING);
                  }
              }
  
              Rlog.d(LOG_TAG, "eriFile = " + eriFile);
  
              if (eriFile == null) {
                  if (DBG) Rlog.e(LOG_TAG, "loadEriFileFromXml: Can't find ERI file to load");
                  return;
              }
  
              try {
                  parser = Xml.newPullParser();
                  parser.setInput(mContext.getAssets().open(eriFile), null);
              } catch (IOException | XmlPullParserException e) {
                  if (DBG) Rlog.e(LOG_TAG, "loadEriFileFromXml: no parser for " + eriFile +
                          ". Exception = " + e.toString());
              }
          }
  
          try {
              XmlUtils.beginDocument(parser, "EriFile");
              mEriFile.mVersionNumber = Integer.parseInt(
                      parser.getAttributeValue(null, "VersionNumber"));
              mEriFile.mNumberOfEriEntries = Integer.parseInt(
                      parser.getAttributeValue(null, "NumberOfEriEntries"));
              mEriFile.mEriFileType = Integer.parseInt(
                      parser.getAttributeValue(null, "EriFileType"));
  
              int parsedEriEntries = 0;
              while(true) {
                  XmlUtils.nextElement(parser);
                  String name = parser.getName();
                  if (name == null) {
                      if (parsedEriEntries != mEriFile.mNumberOfEriEntries)
                          Rlog.e(LOG_TAG, "Error Parsing ERI file: " +  mEriFile.mNumberOfEriEntries
                                  + " defined, " + parsedEriEntries + " parsed!");
                      break;
                  } else if (name.equals("CallPromptId")) {
                      int id = Integer.parseInt(parser.getAttributeValue(null, "Id"));
                      String text = parser.getAttributeValue(null, "CallPromptText");
                      if (id >= 0 && id <= 2) {
                          mEriFile.mCallPromptId[id] = text;
                      } else {
                          Rlog.e(LOG_TAG, "Error Parsing ERI file: found" + id + " CallPromptId");
                      }
  
                  } else if (name.equals("EriInfo")) {
                      int roamingIndicator = Integer.parseInt(
                              parser.getAttributeValue(null, "RoamingIndicator"));
                      int iconIndex = Integer.parseInt(parser.getAttributeValue(null, "IconIndex"));
                      int iconMode = Integer.parseInt(parser.getAttributeValue(null, "IconMode"));
                      String eriText = parser.getAttributeValue(null, "EriText");
                      int callPromptId = Integer.parseInt(
                              parser.getAttributeValue(null, "CallPromptId"));
                      int alertId = Integer.parseInt(parser.getAttributeValue(null, "AlertId"));
                      parsedEriEntries++;
                      mEriFile.mRoamIndTable.put(roamingIndicator, new EriInfo (roamingIndicator,
                              iconIndex, iconMode, eriText, callPromptId, alertId));
                  }
              }
  
              Rlog.d(LOG_TAG, "loadEriFileFromXml: eri parsing successful, file loaded. ver = " +
                      mEriFile.mVersionNumber + ", # of entries = " + mEriFile.mNumberOfEriEntries);
  
              mIsEriFileLoaded = true;
  
          } catch (Exception e) {
              Rlog.e(LOG_TAG, "Got exception while loading ERI file.", e);
          } finally {
              if (parser instanceof XmlResourceParser) {
                  ((XmlResourceParser)parser).close();
              }
              try {
                  if (stream != null) {
                      stream.close();
                  }
              } catch (IOException e) {
                  // Ignore
              }
          }
      }
  
      /**
       * Returns the version of the ERI file
       *
       */
      public int getEriFileVersion() {
          return mEriFile.mVersionNumber;
      }
  
      /**
       * Returns the number of ERI entries parsed
       *
       */
      public int getEriNumberOfEntries() {
          return mEriFile.mNumberOfEriEntries;
      }
  
      /**
       * Returns the ERI file type value ( 0 for Phase 0, 1 for Phase 1)
       *
       */
      public int getEriFileType() {
          return mEriFile.mEriFileType;
      }
  
      /**
       * Returns if the ERI file has been loaded
       *
       */
      public boolean isEriFileLoaded() {
          return mIsEriFileLoaded;
      }
  
      /**
       * Returns the EriInfo record associated with roamingIndicator
       * or null if the entry is not found
       */
      private EriInfo getEriInfo(int roamingIndicator) {
          if (mEriFile.mRoamIndTable.containsKey(roamingIndicator)) {
              return mEriFile.mRoamIndTable.get(roamingIndicator);
          } else {
              return null;
          }
      }
  
      @UnsupportedAppUsage
      private EriDisplayInformation getEriDisplayInformation(int roamInd, int defRoamInd){
          EriDisplayInformation ret;
  
          // Carrier can use carrier config to customize any built-in roaming display indications
          if (mIsEriFileLoaded) {
              EriInfo eriInfo = getEriInfo(roamInd);
              if (eriInfo != null) {
                  if (VDBG) Rlog.v(LOG_TAG, "ERI roamInd " + roamInd + " found in ERI file");
                  ret = new EriDisplayInformation(
                          eriInfo.iconIndex,
                          eriInfo.iconMode,
                          eriInfo.eriText);
                  return ret;
              }
          }
  
          switch (roamInd) {
          // Handling the standard roaming indicator (non-ERI)
          case EriInfo.ROAMING_INDICATOR_ON:
              ret = new EriDisplayInformation(
                      EriInfo.ROAMING_INDICATOR_ON,
                      EriInfo.ROAMING_ICON_MODE_NORMAL,
                      mContext.getText(com.android.internal.R.string.roamingText0).toString());
              break;
  
          case EriInfo.ROAMING_INDICATOR_OFF:
              ret = new EriDisplayInformation(
                      EriInfo.ROAMING_INDICATOR_OFF,
                      EriInfo.ROAMING_ICON_MODE_NORMAL,
                      mContext.getText(com.android.internal.R.string.roamingText1).toString());
              break;
  
          case EriInfo.ROAMING_INDICATOR_FLASH:
              ret = new EriDisplayInformation(
                      EriInfo.ROAMING_INDICATOR_FLASH,
                      EriInfo.ROAMING_ICON_MODE_FLASH,
                      mContext.getText(com.android.internal.R.string.roamingText2).toString());
              break;
  
  
          // Handling the standard ERI
          case 3:
              ret = new EriDisplayInformation(
                      roamInd,
                      EriInfo.ROAMING_ICON_MODE_NORMAL,
                      mContext.getText(com.android.internal.R.string.roamingText3).toString());
              break;
  
          case 4:
              ret = new EriDisplayInformation(
                      roamInd,
                      EriInfo.ROAMING_ICON_MODE_NORMAL,
                      mContext.getText(com.android.internal.R.string.roamingText4).toString());
              break;
  
          case 5:
              ret = new EriDisplayInformation(
                      roamInd,
                      EriInfo.ROAMING_ICON_MODE_NORMAL,
                      mContext.getText(com.android.internal.R.string.roamingText5).toString());
              break;
  
          case 6:
              ret = new EriDisplayInformation(
                      roamInd,
                      EriInfo.ROAMING_ICON_MODE_NORMAL,
                      mContext.getText(com.android.internal.R.string.roamingText6).toString());
              break;
  
          case 7:
              ret = new EriDisplayInformation(
                      roamInd,
                      EriInfo.ROAMING_ICON_MODE_NORMAL,
                      mContext.getText(com.android.internal.R.string.roamingText7).toString());
              break;
  
          case 8:
              ret = new EriDisplayInformation(
                      roamInd,
                      EriInfo.ROAMING_ICON_MODE_NORMAL,
                      mContext.getText(com.android.internal.R.string.roamingText8).toString());
              break;
  
          case 9:
              ret = new EriDisplayInformation(
                      roamInd,
                      EriInfo.ROAMING_ICON_MODE_NORMAL,
                      mContext.getText(com.android.internal.R.string.roamingText9).toString());
              break;
  
          case 10:
              ret = new EriDisplayInformation(
                      roamInd,
                      EriInfo.ROAMING_ICON_MODE_NORMAL,
                      mContext.getText(com.android.internal.R.string.roamingText10).toString());
              break;
  
          case 11:
              ret = new EriDisplayInformation(
                      roamInd,
                      EriInfo.ROAMING_ICON_MODE_NORMAL,
                      mContext.getText(com.android.internal.R.string.roamingText11).toString());
              break;
  
          case 12:
              ret = new EriDisplayInformation(
                      roamInd,
                      EriInfo.ROAMING_ICON_MODE_NORMAL,
                      mContext.getText(com.android.internal.R.string.roamingText12).toString());
              break;
  
          // Handling the non standard Enhanced Roaming Indicator (roamInd > 63)
          default:
              if (!mIsEriFileLoaded) {
                  // ERI file NOT loaded
                  if (DBG) Rlog.d(LOG_TAG, "ERI File not loaded");
                  if(defRoamInd > 2) {
                      if (VDBG) Rlog.v(LOG_TAG, "ERI defRoamInd > 2 ...flashing");
                      ret = new EriDisplayInformation(
                              EriInfo.ROAMING_INDICATOR_FLASH,
                              EriInfo.ROAMING_ICON_MODE_FLASH,
                              mContext.getText(com.android.internal
                                                              .R.string.roamingText2).toString());
                  } else {
                      if (VDBG) Rlog.v(LOG_TAG, "ERI defRoamInd <= 2");
                      switch (defRoamInd) {
                      case EriInfo.ROAMING_INDICATOR_ON:
                          ret = new EriDisplayInformation(
                                  EriInfo.ROAMING_INDICATOR_ON,
                                  EriInfo.ROAMING_ICON_MODE_NORMAL,
                                  mContext.getText(com.android.internal
                                                              .R.string.roamingText0).toString());
                          break;
  
                      case EriInfo.ROAMING_INDICATOR_OFF:
                          ret = new EriDisplayInformation(
                                  EriInfo.ROAMING_INDICATOR_OFF,
                                  EriInfo.ROAMING_ICON_MODE_NORMAL,
                                  mContext.getText(com.android.internal
                                                              .R.string.roamingText1).toString());
                          break;
  
                      case EriInfo.ROAMING_INDICATOR_FLASH:
                          ret = new EriDisplayInformation(
                                  EriInfo.ROAMING_INDICATOR_FLASH,
                                  EriInfo.ROAMING_ICON_MODE_FLASH,
                                  mContext.getText(com.android.internal
                                                              .R.string.roamingText2).toString());
                          break;
  
                      default:
                          ret = new EriDisplayInformation(-1, -1, "ERI text");
                      }
                  }
              } else {
                  // ERI file loaded
                  EriInfo eriInfo = getEriInfo(roamInd);
                  EriInfo defEriInfo = getEriInfo(defRoamInd);
                  if (eriInfo == null) {
                      if (VDBG) {
                          Rlog.v(LOG_TAG, "ERI roamInd " + roamInd
                              + " not found in ERI file ...using defRoamInd " + defRoamInd);
                      }
                      if(defEriInfo == null) {
                          Rlog.e(LOG_TAG, "ERI defRoamInd " + defRoamInd
                                  + " not found in ERI file ...on");
                          ret = new EriDisplayInformation(
                                  EriInfo.ROAMING_INDICATOR_ON,
                                  EriInfo.ROAMING_ICON_MODE_NORMAL,
                                  mContext.getText(com.android.internal
                                                               .R.string.roamingText0).toString());
  
                      } else {
                          if (VDBG) {
                              Rlog.v(LOG_TAG, "ERI defRoamInd " + defRoamInd + " found in ERI file");
                          }
                          ret = new EriDisplayInformation(
                                  defEriInfo.iconIndex,
                                  defEriInfo.iconMode,
                                  defEriInfo.eriText);
                      }
                  } else {
                      if (VDBG) Rlog.v(LOG_TAG, "ERI roamInd " + roamInd + " found in ERI file");
                      ret = new EriDisplayInformation(
                              eriInfo.iconIndex,
                              eriInfo.iconMode,
                              eriInfo.eriText);
                  }
              }
              break;
          }
          if (VDBG) Rlog.v(LOG_TAG, "Displaying ERI " + ret.toString());
          return ret;
      }
  
      public int getCdmaEriIconIndex(int roamInd, int defRoamInd){
          return getEriDisplayInformation(roamInd, defRoamInd).mEriIconIndex;
      }
  
      public int getCdmaEriIconMode(int roamInd, int defRoamInd){
          return getEriDisplayInformation(roamInd, defRoamInd).mEriIconMode;
      }
  
      public String getCdmaEriText(int roamInd, int defRoamInd){
          return getEriDisplayInformation(roamInd, defRoamInd).mEriIconText;
      }
  }
  